Stopping TextBox flicker during update

我与影子孤独终老i 提交于 2019-11-29 13:29:58

The problem is that you are adding (removing) one character at a time repeatedly and quickly. One solution would be to buffer the characters as they are being added and update the textbox at greater intervals (regardless of the amount of characters), for example, every 250 milliseconds.

This would require:

  • to have an array or stack of characters where they get added
  • to have a timer that would call a delegate that would actually do the update with the characters stored in the stack

Another option is to use both every 250 ms and 100 chars, whatever happens first. But this would probably complicate the code more without any tangible benefit.

Mathijs answer is works for me. I've modified it slightly so I can use with any control - a control extension:

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

    }
}

So all you need to do is:

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

Works well. All flickering stops.

Mathijs Beentjes

I found a solution looking on the internet:

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

Have you set double-buffering on your main window?

this code in your constructor after the InitializeComponent call will add double buffering and possibly reduce flicker.

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

Did you try SuspendLayout() / ResumeLayout() around all your update operations?

You could also call Clear() on the textbox then reassign the truncated text.

If your try to implement some kind of log file viewer, you could use a ListBox instead.

I find that using SelectedText = text will reduce the flicker dramatically. For very fast updates, the flicker will be localized to the new text only and you won't get any weird behavior from the scrollbar jumping around.

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

You can also use this to overwrite text written previously -- as you would need for updating a counter or download percentage for example:

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

Other than that, there doesn't seem to be any simple method for reducing flicker in the .NET TextBox.

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