有许多文章解决Windows窗体中的闪烁问题。大多数人建议设置DoubleBuffered = true
或设置一堆ControlStyle
标志。但是,这些都不能帮助减少TextBox闪烁。
以下是一些相关问题:
要重现此问题,请创建一个新的WinForms项目,添加TextBox
,启用多行,禁用自动换行,添加一堆文本,将Anchor
设置为Left + Right + Top +底部。现在运行并调整大小。文字闪烁。对于几个嵌套TableLayoutPanel
内的文本框,调整大小的闪烁更糟。
应用上述问题中提出的解决方案最好不要修复闪烁;如果我获得实验并在ControlStyle
上设置受保护的TextBox
,我可以完全打破它(通过启用UserPaint
)但不能消除闪烁。
那么,有没有办法解决TextBox中文本的闪烁问题?
答案 0 :(得分:15)
我通常使用 RichTextBox 而不是多行TextBox。 通过将DetectUrls-和ShortcutsEnabled-properties设置为false,RTB的行为与TextBox非常相似,并且......它的无闪烁。
答案 1 :(得分:4)
在Windows窗体中,DoubleBuffered属性不会影响子控件(如文本框)。相反,它只会影响它所设置的表单或面板。
如果要对表单上的子元素进行双缓冲,则需要实现手动双缓冲。
鲍勃鲍威尔写了good article(以及其他人)如何做到这一点。
另外,来自forum answer Bob也说:
窗口的所有权意味着 他们会无法控制地闪烁 因为你不能双重缓冲 在目标窗口区域之外。一个 带有子控件的面板不能 使双重缓冲本身和 例如,它是孩子们。
正确执行此操作的唯一方法是 创建一个单一的控件 所有的绘图使用的形式 保留模式图形系统。
因此,要使用手动双缓冲来获取无闪烁的文本框大小调整,您需要以某种方式将文本框呈现到后台缓冲区,然后将其显示为缓冲更新的一部分。如果可能,我不希望这很容易。
[更新]
其他一些答案表示这是Windows Forms特有的问题。这是不正确的,它实际上更深,并且是由Windows GDI引起的。例如,打开记事本/写字板等并粘贴大量文本,调整窗口大小并注意同样的闪烁问题。
这是我多年前用来做类似事情的基本解决方案。它是一个包含多行文本框和从Panel继承的自定义类的简单表单。两个控件具有相同的位置和大小。它使用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);
//this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
}
}
答案 2 :(得分:0)
我们在过去遇到过同样的问题,并且使用了过多的对接和桌面布局面板。如果可能的话,我会建议尝试使用最少的对接来重新构建UI(因为表格布局面板也在内部使用对接)。
答案 3 :(得分:-3)
功能LockWindow AS LONG CONTROL SEND ghDlg,%TEXT_UPPER,%WM_SETREDRAW,0,0 CLEARBuffers 结束功能
功能UnlockWindow AS LONG ClearBuffers CONTROL SEND ghDlg,%TEXT_UPPER,%WM_SETREDRAW,1,0 结束功能