Adsy2010
Adsy2010

Reputation: 545

Logging information to a windowed textbox

I am working on converting a console application into a windowed format and as someone who knows little about it but has had experience with a similar application already in window format in the past I figured it wouldn't be too hard.

So I created a form and added a textbox to it just to get the logging information to start with.

This console app used to run in a single thread, I have since added a second thread to allow the form to run side by side with the console for testing. (it runs fine in a single thread strangely now too).

This is the code I am using to write text to the form except that I am not getting ANYTHING at all on the form.

    static Form1 f = new Form1();
    delegate void SetTextCallback(string s);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (f.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            f.textBox1.Invoke(d, new object[] { text });
        }
        else
        {
            f.textBox1.AppendText(text);
        }
    }

I can confirm that there is text entering the "text" variable but it is not getting to the form.

Any help would be appreciated.

This is the full file:

using System;
using System.Windows.Forms;
using Chraft.Properties;
using System.IO;
using Chraft.Plugins.Events.Args;
using Chraft.Plugins.Events;

namespace Chraft
{
public class Logger
{
    private StreamWriter WriteLog;
    private Server Server;

    internal Logger(Server server, string file)
    {
        Server = server;
        try
        {
            WriteLog = new StreamWriter(file, true);
            WriteLog.AutoFlush = true;
        }
        catch
        {
            WriteLog = null;
        }
    }

    ~Logger()
    {
        try
        {
            WriteLog.Close();
        }
        catch
        {
        }
    }

    public void Log(LogLevel level, string format, params object[] arguments)
    {
        Log(level, string.Format(format, arguments));
    }

    public void Log(LogLevel level, string message)
    {
        //Event
        LoggerEventArgs e = new LoggerEventArgs(this, level, message);
        Server.PluginManager.CallEvent(Event.LOGGER_LOG, e);
        if (e.EventCanceled) return;
        level = e.LogLevel;
        message = e.LogMessage;
        //End Event

        LogToConsole(level, message);
        LogToForm(level, message);
        LogToFile(level, message);
    }

    private void LogToConsole(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            Console.WriteLine(Settings.Default.LogConsoleFormat, DateTime.Now, level.ToString().ToUpper(), message);
        }
    }
    static Form1 f = new Form1();
    delegate void SetTextCallback(string s);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (f.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            f.textBox1.Invoke(d, new object[] { text });
        }
        else
        {
            f.textBox1.AppendText(text);
        }
    }

    private void LogToForm(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            SetText(DateTime.Now + level.ToString().ToUpper() + message);
        }
    }

    private void LogToFile(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogFileLevel && WriteLog != null)
            WriteLog.WriteLine(Settings.Default.LogFileFormat, DateTime.Now, level.ToString().ToUpper(), message);
    }

    public void Log(Exception ex)
    {
        //Event
        LoggerEventArgs e = new LoggerEventArgs(this, LogLevel.Debug, ex.ToString(), ex);
        Server.PluginManager.CallEvent(Event.LOGGER_LOG, e);
        if (e.EventCanceled) return;
        //End Event

        Log(LogLevel.Debug, ex.ToString());
    }


    public enum LogLevel : int
    {
        Trivial = -1,
        Debug = 0,
        Info = 1,
        Warning = 2,
        Caution = 3,
        Notice = 4,
        Error = 5,
        Fatal = 6
    }
}
}

Upvotes: 1

Views: 5070

Answers (2)

Tergiver
Tergiver

Reputation: 14517

The problem is that you are creating two Form objects. One that is created in your Program.cs file: Application.Run(new Form1());

And the one you created in your logger class

Form f = new Form1();

The one passed to Application.Run is the one that the user is interacting with. It has become visible and responds to user interaction because of the Application.Run call.

The one you created on your logger class just sits there in memory. Its TextBox is happily adding the text you ask it to, but that one isn't visible anywhere.

There are many ways to handle this situation. You could gain access to the correct Form object through Application.OpenForms, but a more appropriate way to handle it would be to add an event on the logger that the form can subscribe to and it can handle updating the TextBox in response to the event.

Updated

class LoggerLogEventArgs : EventArgs
{
    public LoggerLogEventArgs(string message)
    {
        this.message = message;
    }
    private string message;
    public string Message { get { return message; } }
}

class Logger
{
    public event EventHandler<LoggerLogEventArgs> Logged;

    protected virtual void OnLogged(LoggerLogEventArgs e)
    {
        EventHandler<LoggerLogEventArgs> handler = Logged;
        if (handler != null)
            handler(this, e);
    }

    // I would change this method name to LogToEvent
    private void LogToForm(LogLevel level, string message)
    {
        if ((int)level >= Settings.Default.LogConsoleLevel)
        {
            OnLogged(new LoggerLogEventArgs(message));
        }
    }
}

class Form1 : Form
{
    // Subscribe to the logger only when we are ready to display text
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        GetLog().Logged += new EventHandler<LoggerLogEventArgs>(logger_Logged);
    }

    // Unsubscribe from the logger before we are no longer ready to display text
    protected override void OnHandleDestroyed(EventArgs e)
    {
        GetLog().Logged -= new EventHandler<LoggerLogEventArgs>(logger_Logged);
        base.OnHandleDestroyed(e);
    }

    private void logger_Logged(object sender, LoggerLogEventArgs e)
    {
        if (InvokeRequired)
            BeginInvoke(new EventHandler<LoggerLogEventArgs>(logger_Logged), e);
        else
            textBox1.AppendText(e.Message);
    }
}

Upvotes: 1

Hassan Boutougha
Hassan Boutougha

Reputation: 3919

hello i try this it works ( I make a console application and I add a windows form)

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Permissions;
using System.Windows.Forms;

namespace ConsoleApplication6
{
    class Program
    {

         delegate void SetTextCallback(string s);
         static Form1 f;

        static void Main(string[] args)
        {      
             f = new Form1();
             f.Show();
             SetText("test");
            Console.ReadLine();
        }
        private static void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (f.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                f.textBox1.Invoke(d, new object[] { text });
            }
            else
            {
                f.textBox1.AppendText(text);
            }
        }
    }

}

Upvotes: 0

Related Questions