如何防止Windows窗体TextBox在调整大小时闪烁?

时间:2009-08-26 09:14:55

标签: .net winforms flicker

有许多文章解决Windows窗体中的闪烁问题。大多数人建议设置DoubleBuffered = true或设置一堆ControlStyle标志。但是,这些都不能帮助减少TextBox闪烁。

以下是一些相关问题:

要重现此问题,请创建一个新的WinForms项目,添加TextBox,启用多行,禁用自动换行,添加一堆文本,将Anchor设置为Left + Right + Top +底部。现在运行并调整大小。文字闪烁。对于几个嵌套TableLayoutPanel内的文本框,调整大小的闪烁更糟。

应用上述问题中提出的解决方案最好不要修复闪烁;如果我获得实验并在ControlStyle上设置受保护的TextBox,我可以完全打破它(通过启用UserPaint)但不能消除闪烁。

那么,有没有办法解决TextBox中文本的闪烁问题?

4 个答案:

答案 0 :(得分:15)

我通常使用 RichTextBox 而不是多行TextBox。 通过将DetectUrls-和ShortcutsEnabled-properties设置为false,RTB的行为与TextBox非常相似,并且......它的无闪烁

答案 1 :(得分:4)

在Windows窗体中,DoubleBuffered属性不会影响子控件(如文本框)。相反,它只会影响它所设置的表单或面板。

如果要对表单上的子元素进行双缓冲,则需要实现手动双缓冲。

鲍勃鲍威尔写了good article(以及其他人)如何做到这一点。

另外,来自forum answer Bob也说:

  

窗口的所有权意味着   他们会无法控制地闪烁   因为你不能双重缓冲   在目标窗口区域之外。一个   带有子控件的面板不能   使双重缓冲本身   例如,它是孩子们。

     

正确执行此操作的唯一方法是   创建一个单一的控件   所有的绘图使用的形式   保留模式图形系统。

因此,要使用手动双缓冲来获取无闪烁的文本框大小调整,您需要以某种方式将文本框呈现到后台缓冲区,然后将其显示为缓冲更新的一部分。如果可能,我不希望这很容易。

[更新]

其他一些答案表示这是Windows Forms特有的问题。这是不正确的,它实际上更深,并且是由Windows GDI引起的。例如,打开记事本/写字板等并粘贴大量文本,调整窗口大小并注意同样的闪烁问题。

这是我多年前用来做类似事情的基本解决方案。它是一个包含多行文本框和从Panel继承的自定义类的简单表单。两个控件具有相同的位置和大小。它使用Forms ResizeBegin和ResizeEnd在调整大小时显示面板,否则显示文本框。它并不完美但它确实消除了闪烁。

   public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Bitmap bm = null;

        private void textBox1_Resize(object sender, EventArgs e)
        {

            Graphics g = textBox1.CreateGraphics();

            if (g.VisibleClipBounds.IsEmpty == false)
            {
                bm = new Bitmap((int)g.VisibleClipBounds.Width, (int)g.VisibleClipBounds.Height);

                textBox1.DrawToBitmap(bm, new Rectangle(0, 0, (int)g.VisibleClipBounds.Width, (int)g.VisibleClipBounds.Height));

            }

            g.Dispose();


        }

        private void panelDB1_Paint(object sender, PaintEventArgs e)
        {
            if (bm != null)
            {
                e.Graphics.DrawImageUnscaled(bm, 0, 0,bm.Width,bm.Height );
            }
        }

        private void Form1_ResizeBegin(object sender, EventArgs e)
        {
            panelDB1.BringToFront();  
        }

        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            panelDB1.SendToBack();   
        }
}

class PanelDB : Panel
{
    public PanelDB()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer,true);       
        //this.DoubleBuffered = true; 

    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
    }
}

答案 2 :(得分:0)

我们在过去遇到过同样的问题,并且使用了过多的对接和桌面布局面板。如果可能的话,我会建议尝试使用最少的对接来重新构建UI(因为表格布局面板也在内部使用对接)。

答案 3 :(得分:-3)

功能LockWindow AS LONG   CONTROL SEND ghDlg,%TEXT_UPPER,%WM_SETREDRAW,0,0   CLEARBuffers 结束功能

功能UnlockWindow AS LONG   ClearBuffers   CONTROL SEND ghDlg,%TEXT_UPPER,%WM_SETREDRAW,1,0 结束功能