首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何防止Windows Forms TextBox在调整大小时闪烁?

如何防止Windows Forms TextBox在调整大小时闪烁?
EN

Stack Overflow用户
提问于 2009-08-26 09:14:55
回答 4查看 15.6K关注 0票数 19

有很多关于Windows窗体中的闪烁的文章。大多数人建议设置DoubleBuffered = true或设置一堆ControlStyle标志。然而,这些都不能帮助减少TextBox闪烁。

这里有几个相关的问题:

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

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

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-04-15 22:45:17

我通常使用RichTextBox而不是多行TextBox。通过将DetectUrls和ShortcutsEnabled属性设置为false,RTB的行为非常类似于TextBox和...它没有闪烁。

票数 16
EN

Stack Overflow用户

发布于 2009-08-26 09:59:15

在Windows窗体中,DoubleBuffered属性不影响文本框等子控件。相反,它只影响为其设置的窗体或面板。

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

Bob Powell写了一篇关于如何做到这一点的good article (和其他人)。

此外,来自forum answer的鲍勃还说:

窗口的所有权意味着它们将无法控制地闪烁,因为您不能在目标窗口区域之外进行双缓冲。具有子控件的面板不能将其自身及其子控件设置为双缓冲区。

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

因此,要使用手动双缓冲获得无闪烁的文本框大小,您需要以某种方式将文本框渲染到后台缓冲区,然后将其显示为缓冲更新的一部分。即使可能:我也不认为这会是一件容易的事情。

更新

其他一些回答说这是Windows窗体的一个具体问题。这是不正确的,它实际上是更深层次的,是由Windows GDI引起的。例如,打开记事本/写字板等,粘贴一大块文本,调整窗口大小,注意到同样的闪烁问题。

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

代码语言:javascript
复制
   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);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2009-08-26 09:52:19

我们在过去遇到过类似的问题,结果是使用了过多的停靠和表格布局面板。我会建议,如果可能的话,尝试用最少的停靠来重建UI (因为表格布局面板也在内部使用停靠)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1333393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档