如何防止Windows窗体文本框从闪烁的大小?(How to prevent a Windows F

2019-07-03 17:38发布

有很多的文章在Windows窗体解决闪烁。 大多数建议设置DoubleBuffered = true或设置一堆ControlStyle标志。 然而,这些都不利于降低一个TextBox闪烁。

下面是几个相关问题:

  • 如何在窗体上双缓冲.NET控件?
  • 如何滚动时消除Windows.Forms的自定义控件闪烁?

要重现该问题,创建一个新的WinForms项目,添加一个TextBox ,支持多行,禁用自动换行,加了一堆文字,设置Anchor到左+右+上衣+底。 现在运行和调整大小。 文字闪烁。 一对夫妇的嵌套在文本框TableLayoutPanel S于调整大小的闪烁更是雪上加霜。

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

那么,有没有办法在所有固定在一个文本框中的文本的闪烁?

Answer 1:

我通常使用一个RichTextBox,而不是一个多行TextBox的。 通过DetectUrls-和ShortcutsEnabled的属性设置为false RTB的行为非常相似,一个文本框和......这是无闪烁



Answer 2:

在Windows窗体的DoubleBuffered属性不影响子控件如文本框。 相反,它会影响只是窗体或面板被设置。

如果你想为一个窗体上的子元素双缓冲,你将需要实现手动双缓冲。

鲍勃鲍威尔写了一篇好文章就如何做到这一点(和其他人)。

此外,从一个论坛的答案鲍勃也说:

窗口的所有权意味着他们将闪烁失控,因为你不能双缓冲器的目标窗口区域之外。 与子控件面板无法进行双重缓冲本身它的孩子的例子。

正确地做到这一点的唯一方法是创建一个单一的控制,做使用保留模式图形系统的表单中的所有图纸。

因此,为了获得无闪烁的文本框,调整使用手动双缓冲您需要的文本框某种程度上呈现到你的后缓冲区,然后显示它作为缓冲更新的一部分。 如果甚至有可能,我不希望这会很容易。

[更新]

一些其他答案说这是与Windows窗体明确的一个问题。 这是不正确的,它实际上是更深那么与由Windows GDI引起的。 作为一个例子,打开记事本/写字板等和粘贴大块的文本,调整窗口的大小,并注意同闪烁的问题。

下面是我用几年前做同样的事情碱性溶液。 它是含有多行文本框和自定义类从面板继承的简单形式。 这两个控件都具有相同的位置和大小。 它采用的形式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);
    }
}


Answer 3:

我们遇到了同类的过去的问题,它出来是过度使用的对接和表布局面板。 我会建议,如果可能的话,尽量使用最少的对接,重新构建UI(如表布局面板还采用了对接内部)。



Answer 4:

功能LockWindow只要控制发送ghDlg,%TEXT_UPPER,WM_SETREDRAW%,0,0 CLEARBuffers END FUNCTION

功能UnlockWindow只要ClearBuffers CONTROL发送ghDlg,%TEXT_UPPER,WM_SETREDRAW%,1,0 END FUNCTION



文章来源: How to prevent a Windows Forms TextBox from flickering on resize?