How to prevent a Windows Forms TextBox from flickering on resize?

你。 提交于 2019-11-27 21:17:13

I usually use a RichTextBox instead of a multiline TextBox. By setting the DetectUrls- and ShortcutsEnabled-properties to false the RTB behaves very similar to a TextBox and ... it's flicker-free.

In Windows Forms the DoubleBuffered property does not affect child controls such as text boxes. Instead it affects just the form or Panel it is set for.

If you want double buffering for child elements on a form, you will need to implement manual double buffering.

Bob Powell has written a good article (and others) on how to do this.

Also, from a forum answer Bob also says:

The ownership of a window means that they will flicker uncontrollably because you cannot double-buffer outside of the target windows area. A panel with child controls cannot be made to double buffer itself and it's children for example.

The only way to do this correctly is to create a single control that does all the drawing using a form of retained mode graphics system.

Therefore, to get flicker free textbox resize using manual double buffering you would need to somehow render the textbox to your back buffer and then display it as part of the buffered update. If even possible, I do not expect this would be easy.

[Update]

Some other answers have said this is a problem with Windows Forms specifically. This is not correct, it is actually deeper then that and is caused by Windows GDI. As an example, open Notepad / Wordpad etc and paste a large chunk of text, resize the window and notice the same flickering issue.

Here is a basic solution I used years ago to do something similar. It is a simple form containing a multiline textbox and a custom class inheriting from Panel. Both controls have the same location and size. It uses the Forms ResizeBegin and ResizeEnd to show the panel when resizing, and the textbox otherwise. It's not perfect but it does eliminate the flickering.

   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);
    }
}

We have encountered same kind of problem in past and it comes out to be use of excessive docking and table layout panels. I will suggest, if possible, try to re-construct the UI with minimal use of docking (as table layout panel also uses docking internally).

FUNCTION LockWindow AS LONG CONTROL SEND ghDlg, %TEXT_UPPER,%WM_SETREDRAW,0,0 CLEARBuffers END FUNCTION

FUNCTION UnlockWindow AS LONG ClearBuffers CONTROL SEND ghDlg,%TEXT_UPPER,%WM_SETREDRAW,1,0 END FUNCTION

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!