在Windows Forms中,DoubleBuffered属性不会影响文本框等子控件。它只会影响设置了该属性的窗体或面板。
如果您想在窗体上实现子元素的双缓冲,您需要手动实现双缓冲。
Bob Powell撰写了一篇关于如何做到这一点的
好文章(以及其他文章)。
此外,根据Bob在
论坛答案中的说法:
拥有一个窗口意味着它们将无法控制地闪烁,因为您无法在目标窗口区域之外进行双缓冲。例如,带有子控件的面板不能使自己和其子控件都进行双缓冲。
正确的方法是创建一个单独的控件,使用保留模式图形系统进行所有绘图。
因此,要使用手动双缓冲获得无闪烁的文本框调整大小,您需要以某种方式将文本框呈现到后台缓冲区,并将其作为缓冲更新的一部分显示。如果可能的话:我不认为这会很容易。
[更新]
其他答案称这是Windows Forms特有的问题。这是不正确的,实际上这是由Windows GDI引起的更深层次的问题。例如,打开记事本/字处理软件等并粘贴大块文本,调整窗口大小,注意到相同的闪烁问题。
以下是我多年前用来做类似事情的基本解决方案。它是一个包含多行文本框和从面板继承的自定义类的简单表单。两个控件具有相同的位置和大小。它使用Forms 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);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
}
}