有很多关于Windows窗体中的闪烁的文章。大多数人建议设置DoubleBuffered = true
或设置一堆ControlStyle
标志。然而,这些都不能帮助减少TextBox闪烁。
这里有几个相关的问题:
要重现这个问题,请创建一个新的WinForms项目,添加一个TextBox
,启用多行,禁用自动换行,添加一堆文本,将Anchor
设置为Left+Right+Top+Bottom。现在运行并调整大小。文本闪烁。对于两个嵌套的TableLayoutPanel
中的文本框,调整大小时的闪烁甚至更糟。
应用上述问题中提出的解决方案充其量并不能修复闪烁;如果我进行了实验,并在TextBox
上设置了受保护的ControlStyle
,我可以完全打破它(通过启用UserPaint
),但不能消除闪烁。
那么,有没有办法解决TextBox中文本闪烁的问题呢?
发布于 2011-04-15 14:45:17
我通常使用RichTextBox而不是多行TextBox。通过将DetectUrls和ShortcutsEnabled属性设置为false,RTB的行为非常类似于TextBox和...它没有闪烁。
发布于 2009-08-26 01:59:15
在Windows窗体中,DoubleBuffered属性不影响文本框等子控件。相反,它只影响为其设置的窗体或面板。
如果要对窗体上的子元素进行双缓冲,则需要实现手动双缓冲。
Bob Powell写了一篇关于如何做到这一点的good article (和其他人)。
此外,来自forum answer的鲍勃还说:
窗口的所有权意味着它们将无法控制地闪烁,因为您不能在目标窗口区域之外进行双缓冲。具有子控件的面板不能将其自身及其子控件设置为双缓冲区。
正确执行此操作的唯一方法是创建单个控件,该控件使用保留模式图形系统的形式完成所有绘图。
因此,要使用手动双缓冲获得无闪烁的文本框大小,您需要以某种方式将文本框渲染到后台缓冲区,然后将其显示为缓冲更新的一部分。即使可能:我也不认为这会是一件容易的事情。
更新
其他一些回答说这是Windows窗体的一个具体问题。这是不正确的,它实际上是更深层次的,是由Windows GDI引起的。例如,打开记事本/写字板等,粘贴一大块文本,调整窗口大小,注意到同样的闪烁问题。
这是几年前我用来做类似事情的一个基本解决方案。它是一个简单的表单,包含一个多行文本框和一个继承自Panel的自定义类。这两个控件具有相同的位置和大小。它在调整大小时使用窗体ResizeBegin和ResizeEnd来显示面板,否则使用textbox。它不是完美的,但它确实消除了闪烁。
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);
}
}
发布于 2009-08-26 01:52:19
我们在过去遇到过类似的问题,结果是使用了过多的停靠和表格布局面板。我会建议,如果可能的话,尝试用最少的停靠来重建UI (因为表格布局面板也在内部使用停靠)。
https://stackoverflow.com/questions/1333393
复制相似问题