更新期间停止闪烁的TextBox(Stopping TextBox flicker during u

2019-07-22 00:46发布

我的WinForms应用程序,我使用的日志文件,一个文本框。 我不使用形式闪烁文本追加TextBox.AppendText(string); ,但是当我试图清除旧文本(如控制的。文本属性达到.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();
    }
}

有没有从不会导致闪烁控制的顶部清除文本行的一个更合适的方法? 一个文本框不具有的BeginUpdate()/ EndUpdate()的一个ListView具有的方法。

是一个TextBox控件,即使是控制台日志中最适合控制?

编辑:文本框闪烁似乎是文本框滚动到顶部(而我在净化控制的顶部的文本),然后立即滚动回落至底部。 - 这一切发生得很快,所以我刚才看到重复闪烁。

我也只是看到了这个问题 ,并建议是使用一个列表框,但我不知道这是否会在我的情况下工作,因为(在大多数情况下)我收到的为ListBox一个字符文本的时间。

Answer 1:

问题是,你是反复和快速增加(删除)一个字符的时间。 一个解决办法是将缓冲字符作为被添加它们,并更新以更大的间隔文本框(无论字符的量),例如,每250毫秒。

这就要求:

  • 具有在那里它们被添加字符数组或堆
  • 有一个计时器,将调用一个委托,它实际上会做更新存储在堆栈中的字符

另一种选择是使用每250毫秒和100个字符,不管发生了第一次两个。 但是,这可能会变得复杂的代码更没有任何实际的好处。



Answer 2:

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

效果很好。 所有闪烁停止。



Answer 3:

我发现寻找在互联网上的解决方案:

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


Answer 4:

你有你的主窗口上设置双缓冲?

这个代码在InitializeComponent调用后,你的构造将增加双缓冲,并可能减少闪烁。

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



Answer 5:

你有没有尝试SuspendLayout()/ ResumeLayout()在你所有的更新操作?

您也可以致电文本框中清除()然后重新分配的文本被截断。

如果你试图实现某种形式的日志文件查看器,你可以使用一个列表框来代替。



Answer 6:

我发现,使用SelectedText =文本将大大减少闪烁。 对于非常快速更新,闪烁将被定位于只新的文本,你不会得到滚动条跳来跳去任何怪异的行为。

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文本框减少闪烁任何简单的方法。



文章来源: Stopping TextBox flicker during update