1

我正在努力将控制台应用程序转换为窗口格式,作为一个对此知之甚少但过去曾使用过类似窗口格式的类似应用程序的人,我认为这不会太难。

所以我创建了一个表单并在其中添加了一个文本框,只是为了获取日志信息。

这个控制台应用程序曾经在单个线程中运行,此后我添加了第二个线程以允许表单与控制台并排运行以进行测试。(它现在也奇怪地在一个线程中运行良好)。

这是我用来将文本写入表单的代码,除了我在表单上没有得到任何东西。

    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);
        }
    }

我可以确认有文本输入“文本”变量,但它没有进入表单。

任何帮助,将不胜感激。

这是完整的文件:

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
    }
}
}
4

2 回答 2

1

问题是您正在创建两个 Form 对象。在您的 Program.cs 文件中创建的一个:Application.Run(new Form1());

还有你在记录器类中创建的那个

表格 f = 新表格 1();

传递给 Application.Run 的是用户正在与之交互的那个。由于 Application.Run 调用,它变得可见并响应用户交互。

您在 logger 类上创建的那个只是在内存中。它的 TextBox 很乐意添加您要求它添加的文本,但该文本在任何地方都不可见。

有很多方法可以处理这种情况。您可以通过 Application.OpenForms 访问正确的 Form 对象,但更合适的处理方法是在记录器上添加一个表单可以订阅的事件,它可以处理更新 TextBox 以响应该事件。

更新

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);
    }
}
于 2012-08-30T22:29:10.887 回答
0
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);
            }
        }
    }

}
于 2012-08-30T20:05:21.927 回答