更新期间停止TextBox闪烁

我的WinForms应用程序有一个TextBox,我将其用作日志文件。 我正在使用TextBox.AppendText(string);附加没有闪烁forms的文本TextBox.AppendText(string); 但是当我尝试清除旧文本时(因为控件的.Text属性达到.MaxLength限制),我得到了可怕的闪烁。

我正在使用的代码如下:

 public static void AddTextToConsoleThreadSafe(TextBox textBox, string text) { if (textBox.InvokeRequired) { textBox.Invoke(new AddTextToConsoleThreadSafeDelegate(AddTextToConsoleThreadSafe), new object[] { textBox, text }); } else { // Ensure that text is purged from the top of the textbox // if the amount of text in the box is approaching the // MaxLength property of the control if (textBox.Text.Length + text.Length > textBox.MaxLength) { int cr = textBox.Text.IndexOf("\r\n"); if (cr > 0) { textBox.Select(0, cr + 1); textBox.SelectedText = string.Empty; } else { textBox.Select(0, text.Length); } } // Append the new text, move the caret to the end of the // text, and ensure the textbox is scrolled to the bottom textBox.AppendText(text); textBox.SelectionStart = textBox.Text.Length; textBox.ScrollToCaret(); } } 

是否有更简洁的方法从控件顶部清除不会引起闪烁的文本行? 文本框没有ListView具有的BeginUpdate()/ EndUpdate()方法。

TextBox控件是控制台日志的最佳控件吗?

编辑:TextBox闪烁似乎是向上滚动的文本框(当我清除控件顶部的文本时),然后它立即向下滚动到底部。 – 这一切都很快发生,所以我只是看到反复的闪烁。

我也刚刚看到这个问题 ,建议是使用ListBox,但我不知道这是否适用于我的情况,因为(在大多数情况下)我收到了ListBox的文字一个字符在一时间

问题是您反复且快速地一次添加(删除)一个字符。 一种解决方案是在添加字符时缓冲字符,并以更大的间隔(无论字符数量)更新文本框,例如,每250毫秒。

这需要:

  • 有一个数组或一堆字符添加它们
  • 有一个计时器,可以调用一个委托,该委托实际上将使用存储在堆栈中的字符进行更新

另一个选择是每250毫秒和100个字符使用,无论先发生什么。 但这可能会使代码复杂化而没有任何实际好处。

我在互联网上找到了一个解决方案:

  [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern bool LockWindowUpdate(IntPtr hWndLock); internal void FillTB(TextBox tb, string mes) { try { LockWindowUpdate(tb.Handle); // Do your thingies with TextBox tb } finally { LockWindowUpdate(IntPtr.Zero); } } 

Mathijs的答案对我有用。 我稍微修改了它,所以我可以使用任何控件 – 控件扩展:

 namespace System.Windows.Forms { public static class ControlExtensions { [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern bool LockWindowUpdate(IntPtr hWndLock); public static void Suspend(this Control control) { LockWindowUpdate(control.Handle); } public static void Resume(this Control control) { LockWindowUpdate(IntPtr.Zero); } } } 

所以你需要做的就是:

 myTextBox.Suspend(); // do something here. myTextBox.Resume(); 

效果很好。 所有闪烁停止。

你有没有在主窗口设置双缓冲?

在InitializeComponent调用之后,构造函数中的此代码将添加双缓冲并可能减少闪烁。

this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer,true);

您是否在所有更新操作周围尝试了SuspendLayout()/ ResumeLayout()?

您也可以在文本框上调用Clear(),然后重新分配截断的文本。

如果您尝试实现某种日志文件查看器,则可以使用ListBox。

我发现使用SelectedText = text会显着减少闪烁。 对于非常快速的更新,闪烁将仅本地化为新文本,并且您不会从滚动条跳转到任何奇怪的行为。

 void UpdateTextBox(string message) { myTextBox.SelectionStart = myTextBox.Text.Length; myTextBox.SelectedText = message; } 

您也可以使用它来覆盖之前写入的文本 – 例如,您需要更新计数器或下载百分比:

 void UpdateTextBox(string message, int jumpBack) { myTextBox.SelectionStart = Math.Max(myTextBox.Text.Length - jumpBack, 0); myTextBox.SelectionLength = jumpBack; myTextBox.SelectedText = message; } 

除此之外,似乎没有任何简单的方法来减少.NET TextBox中的闪烁。