在C#WinForm中管理错误/状态文本框

在C#WinForm中管理错误/状态文本框,c#,winforms,textbox,status,C#,Winforms,Textbox,Status,我正在编写一个用于管理字幕文件的UI,它提供了对文件的一些操作,并有一个错误/状态文本框(实际上是一个富文本框)。 我希望能够向文本框中添加指示长操作状态的行,因此我执行了以下操作: StatusErrors.Text+=“更改开始时间,正在处理字幕文件…\n”; 长时间操作(状态错误); StatusErrors.Text+=“完成\n” 但我看到的唯一文本是操作结束时的“完成”,这是为什么?尝试使用 StatusErrors.AppendText(“错误消息”) 您只能看到“完成”文本,因

我正在编写一个用于管理字幕文件的UI,它提供了对文件的一些操作,并有一个错误/状态文本框(实际上是一个富文本框)。 我希望能够向文本框中添加指示长操作状态的行,因此我执行了以下操作:


StatusErrors.Text+=“更改开始时间,正在处理字幕文件…\n”;
长时间操作(状态错误);
StatusErrors.Text+=“完成\n”

但我看到的唯一文本是操作结束时的“完成”,这是为什么?

尝试使用 StatusErrors.AppendText(“错误消息”)

您只能看到“完成”文本,因为您在与长时间运行的方法相同的线程中更新UI,这会导致在操作运行时锁定UI。使用
BackgroundWorker
DoWork
事件执行长时间运行的操作,并更新
ProgressChanged
事件中的状态文本。
BackgroundWorker
的另一种选择是在每次状态更新后调用
Application.DoEvents()

我的猜测(目前只是猜测)是可能会出现问题,因为您使用“\n”换行。相反,尝试使用以下方法:

StatusErrors.Text = "Log line 1" + Environment.NewLine;
后来

StatusErrors.AppendText("Log line 2" + Environment.NewLine);
一旦你有足够的文本,你会注意到RichTextBox不会自动滚动到文本的末尾,而自动滚动会很麻烦。(如果您执行类似于
StatusErrors.Text+=“Blah Blah.”
的操作,每次都会重置您的位置,而
.AppendText
我不相信会这样做。)现在,使用WPF很容易,因为有一个
ScrollToEnd
函数,但使用常规WinForms可能会更复杂一些。我认为最常用的方法是

StatusErrors.SelectionLength = 0;
StatusErrors.SelectionStart = StatusErrors.Text.Length - 1;
StatusErrors.ScrollToCaret();
我认为这有其问题:例如,它将文本框置于焦点位置。另一种方法是使用Windows API函数实现它

// from http://bitmatic.com/c/implementing-a-scrolling-richtextbox

class ScrollingRichTextBox : System.Windows.Forms.RichTextBox
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(
      IntPtr hWnd,
      uint Msg,
      IntPtr wParam,
      IntPtr lParam);

    private const int WM_VSCROLL = 277;
    private const int SB_LINEUP = 0;
    private const int SB_LINEDOWN = 1;
    private const int SB_TOP = 6;
    private const int SB_BOTTOM = 7;

    public void ScrollToBottom()
    {
        SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_BOTTOM), new IntPtr(0));
    }

    public void ScrollToTop()
    {
        SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_TOP), new IntPtr(0));
    }

    public void ScrollLineDown()
    {
        SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_LINEDOWN), new IntPtr(0));
    }

    public void ScrollLineUp()
    {
        SendMessage(Handle, WM_VSCROLL, new IntPtr(SB_LINEUP), new IntPtr(0));
    }
}

此外,如中所述,如果您希望写入日志并在方法中执行同步等待时更新日志,则可能的解决方案是在写入后调用
Application.DoEvents()

您需要显示该
longOperation
函数的代码。请尝试在窗体上调用Update()(更改后),更改可能会在下次运行时更新。在longOperation()之前调用StatusErrors.Update()可以让您将使用线程的时间推迟一段时间。