我的WinForms应用程序有一个TextBox,我将其用作日志文件。我使用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闪烁似乎是向上滚动的文本框(当我清除控件顶部的文本时),然后它立即向下滚动到底部。 - 这一切都很快发生,所以我只是看到反复闪烁。
我刚看到this question,建议是使用ListBox,但我不知道这是否适用于我的情况,因为(在大多数情况下)我收到了文字对于ListBox一次只能有一个字符。
答案 0 :(得分:12)
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();
运作良好。所有闪烁停止。
答案 1 :(得分:11)
我找到了一个在互联网上寻找的解决方案:
[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);
}
}
答案 2 :(得分:3)
您是否在主窗口上设置了双缓冲?
在InitializeComponent调用之后,构造函数中的此代码将添加双缓冲并可能减少闪烁。
this.SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer,true);
答案 3 :(得分:2)
您是否围绕所有更新操作尝试了SuspendLayout()/ ResumeLayout()?
您也可以在文本框上调用Clear(),然后重新分配截断的文本。
如果您尝试实现某种日志文件查看器,则可以使用ListBox。
答案 4 :(得分:2)
问题在于您反复且快速地一次添加(删除)一个字符。一种解决方案是在添加字符时缓冲字符,并以更大的间隔(无论字符数量)更新文本框,例如,每250毫秒。
这需要:
另一个选择是每250毫秒和100个字符使用,无论先发生什么。但这可能会使代码更加复杂,而没有任何实际的好处。
答案 5 :(得分:2)
我发现使用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中的闪烁。