WinForms中TextBox通过Timer更新时闪烁问题求助
解决WinForms中Timer更新TextBox的闪烁问题
核心原因
每次通过MainText.Text = lk.ToString()全量赋值文本,会触发TextBox的完整重绘,加上Timer频繁触发Tick事件,就会导致明显的闪烁。
具体修复方案
1. 给TextBox开启双缓冲
WinForms原生TextBox默认未启用双缓冲,自定义一个继承自TextBox的控件开启该特性:
public class DoubleBufferedTextBox : TextBox { public DoubleBufferedTextBox() { SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); } }
将窗体上的原TextBox替换为这个自定义控件即可。
2. 避免全量更新文本,改用局部修改
原代码每次替换单个字符后就重新赋值整个字符串,改为直接修改TextBox中指定位置的字符,大幅减少重绘范围:
修改后的Tick事件代码:
private void timer1_Tick(object sender, EventArgs e) { if (count < lk.Length) { if (lk[count] == '\r' && count + 1 < lk.Length && lk[count + 1] == '\n') { count += 2; // 移动光标到新位置 MainText.SelectionStart = count; MainText.ScrollToCaret(); } else { // 直接修改指定位置的字符,无需全量赋值 MainText.SelectionStart = count; MainText.SelectionLength = 1; MainText.SelectedText = "_"; lk[count] = '_'; count++; MainText.ScrollToCaret(); } } else { timer1.Stop(); count = 0; } }
3. 更新前暂停TextBox绘制(可选,配合前两种方法效果更好)
通过Windows API发送消息,在更新文本前暂停绘制,完成后再恢复:
先添加API声明:
private const int WM_SETREDRAW = 0x000B; [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
然后修改Tick事件:
private void timer1_Tick(object sender, EventArgs e) { // 暂停绘制 SendMessage(MainText.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero); if (count < lk.Length) { if (lk[count] == '\r' && count + 1 < lk.Length && lk[count + 1] == '\n') { count += 2; MainText.SelectionStart = count; MainText.ScrollToCaret(); } else { MainText.SelectionStart = count; MainText.SelectionLength = 1; MainText.SelectedText = "_"; lk[count] = '_'; count++; MainText.ScrollToCaret(); } } else { timer1.Stop(); count = 0; } // 恢复绘制并刷新 SendMessage(MainText.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); MainText.Invalidate(); }
推荐组合
优先使用自定义双缓冲TextBox + 局部修改文本的组合,基本可以解决大部分闪烁问题;如果仍有轻微闪烁,再加上暂停绘制的逻辑。
内容的提问来源于stack exchange,提问作者Dmitriy Matveev
相关产品推荐
相关产品推荐

