将 Console.WriteLine() 重定向到文本框

Posted

技术标签:

【中文标题】将 Console.WriteLine() 重定向到文本框【英文标题】:Redirecting Console.WriteLine() to Textbox 【发布时间】:2013-09-14 15:09:13 【问题描述】:

我正在使用 C# 在 Visual Studio 2010 中构建此应用程序。

基本上有2个文件,form1.cs(即windows窗体)和program.cs(所有逻辑所在)。

//form1.cs
public partial class Form1 : Form

    //runButton_click function


//program.cs
class Program

    static void Main()
    
        while(blah-condition)
        
            //some calculation
            Console.WriteLine("Progress " + percent + "% completed.");
        
    

有一个运行按钮和一个空白文本框

当用户点击“运行”按钮时,program.cs 将执行一些任务,并使用Console.WriteLine() 将进度不断打印到控制台(命令提示符)上。

问题:如何打印到 form1 上的文本框而不是打印到命令提示符? 我需要不断地打印进度,而无需任何用户操作。

提前致谢!

顺便说一句,它不一定是文本框,它可以是标签或其他可以接受文本的东西。我选择了文本框,因为它对我来说更有意义。

【问题讨论】:

虽然您的原始问题似乎已得到解答,但请注意,如果您正在向文本框发送大量更新,因为您可能会淹没您的消息队列,从而导致表单变得非常无响应。表单响应能力还取决于“一些计算”的强度。您可能需要考虑一个将进度报告回表单的后台工作线程。 @RickDavin 请注意,这种替代方法需要能够将所有控制台写入更改为其他内容。如果他无法控制该代码(即它是库代码),那可能不是一个选项,或者它可能不实用。 【参考方案1】:

textbox 放在表单上(multiple lines 已启用)或文本区域,然后您可以在循环中进行操作

txtOutput.Text += "Progress " + percent + "% completed." + Environment.NewLine();

【讨论】:

问题是,循环在program.cs中,无法识别文本框,文本框只存在于form1.cs中 那么不要使用控制台应用程序...只需使用简单的 GUI 应用程序即可【参考方案2】:

不知道它是否会起作用,但您可以尝试重定向控制台输出。

使用Console.SetOut() 并创建TextWriter 的派生类,它会覆盖WriteLine() 方法,只需将方法参数分配给您的TextBox.Text 应该可以。

【讨论】:

【参考方案3】:

我将这样的东西用于列表框:

    public class ListBoxWriter : TextWriter //this class redirects console.writeline to debug listbox

    private readonly ListBox _list;
    private StringBuilder _content = new StringBuilder();

    public ListBoxWriter(ListBox list)
    
        _list = list;
    

    public override Encoding Encoding
    
        get  return Encoding.UTF8; 
    
    public override void Write(char value)
    
        base.Write(value);
        _content.Append(value);

        if (value != '\n') return;
        if (_list.InvokeRequired)
        
            try
            
                _list.Invoke(new MethodInvoker(() => _list.Items.Add(_content.ToString())));
                _list.Invoke(new MethodInvoker(() => _list.SelectedIndex = _list.Items.Count - 1));
                _list.Invoke(new MethodInvoker(() => _list.SelectedIndex = -1));
            
            catch (ObjectDisposedException ex)
            
                Console.WriteLine(Resources.Exception_raised + " (" + ex.Message + "): " + ex);
            
        
        else
        
            _list.Items.Add(_content.ToString());
            _list.SelectedIndex = _list.Items.Count - 1;
            _list.SelectedIndex = -1;
        
        _content = new StringBuilder();
    

在我的主应用程序中:

_writer = new ListBoxWriter(DebugWin); // DebugWin is the name og my listbox

Console.SetOut(_writer);

【讨论】:

【参考方案4】:

首先创建一个能够写入文本框的新TextWriter。它只需要覆盖接受charWrite 方法,但这会非常低效,因此最好至少用字符串覆盖该方法。

public class ControlWriter : TextWriter

    private Control textbox;
    public ControlWriter(Control textbox)
    
        this.textbox = textbox;
    

    public override void Write(char value)
    
        textbox.Text += value;
    

    public override void Write(string value)
    
        textbox.Text += value;
    

    public override Encoding Encoding
    
        get  return Encoding.ASCII; 
    

在这种情况下,我让它只接受Control,它可以是TextboxLabel 或其他。如果您想将其更改为 Label,那很好。

然后只需将控制台输出设置为该编写器的新实例,指向某个文本框或标签:

Console.SetOut(new ControlWriter(textbox1));

如果您希望将输出写入控制台以及到文本框,我们可以使用这个类来创建一个写入器,它将写入多个写入器:

public class MultiTextWriter : TextWriter

    private IEnumerable<TextWriter> writers;
    public MultiTextWriter(IEnumerable<TextWriter> writers)
    
        this.writers = writers.ToList();
    
    public MultiTextWriter(params TextWriter[] writers)
    
        this.writers = writers;
    

    public override void Write(char value)
    
        foreach (var writer in writers)
            writer.Write(value);
    

    public override void Write(string value)
    
        foreach (var writer in writers)
            writer.Write(value);
    

    public override void Flush()
    
        foreach (var writer in writers)
            writer.Flush();
    

    public override void Close()
    
        foreach (var writer in writers)
            writer.Close();
    

    public override Encoding Encoding
    
        get  return Encoding.ASCII; 
    

然后使用这个我们可以做到:

Console.SetOut(new MultiTextWriter(new ControlWriter(textbox1), Console.Out));

【讨论】:

我放“Console.SetOut(new TextboxWriter(textbox1));”在 Main() withing program.cs 里面? program.cs 无法识别在 form1.cs 中且在 program.cs 中不存在的 textbox1 @sora0419 不,你应该把它放在表单的定义中。 当我创建 ControlWriter 时,我收到一条错误消息“'ControlWriter' 没有实现继承的抽象成员 'System.IO.TextWriter.Encoding.get'”我错过了什么? @sora0419 只需为编码添加一个实现。 我尝试了第一种方法。该程序停止打印到控制台,但是文本框中也没有打印任何内容。我将 ControlWriter 类放在命名空间 Form1 内,但放在公共部分类 Form1 之外:Form。我把“Console.SetOut(new ControlWriter(textbox1));”在 InitializeComponent() 之后的 Form1 类中;我是否误解了某些东西并将功能放在了错误的位置?

以上是关于将 Console.WriteLine() 重定向到文本框的主要内容,如果未能解决你的问题,请参考以下文章

C#中Console.WriteLine与Response.Write有啥区别

带有用户定义对象向量的 C++/CLI Console::WriteLine

C#中的format和console.writeline有啥区别

Debug.WriteLine() 与 Console.WriteLine() 处理文化的方式不同。为啥?

c#输入语句

Console.WriteLine() 在发布期间写入啥? [复制]