Rom*_*kov 17 .net flicker winforms
有很多文章解决Windows窗体中的闪烁问题.大多数人建议设置DoubleBuffered = true或设置一堆ControlStyle标志.但是,这些都不能帮助减少TextBox闪烁.
以下是一些相关问题:
要重现该问题,请创建一个新的WinForms项目,添加一个TextBox,启用多行,禁用自动换行,添加一堆文本,设置Anchor为Left + Right + Top + Bottom.现在运行并调整大小.文字闪烁.对于几个嵌套TableLayoutPanels中的文本框,调整大小时的闪烁更糟.
应用上述问题中提出的解决方案最好不要修复闪烁; 如果我得到实验并设置受保护ControlStyle,TextBox我可以完全打破它(通过启用UserPaint),但不能消除闪烁.
那么,有没有办法解决TextBox中文本的闪烁问题?
mia*_*eck 15
我通常使用RichTextBox而不是多行TextBox.通过将DetectUrls-和ShortcutsEnabled-properties设置为false,RTB的行为与TextBox非常相似,并且......它没有闪烁.
在 Windows 窗体中,DoubleBuffered 属性不会影响子控件(例如文本框)。相反,它仅影响为其设置的表单或面板。
如果您想对表单上的子元素进行双缓冲,则需要实现手动双缓冲。
鲍勃·鲍威尔(Bob Powell)写了一篇关于如何做到这一点的好文章(以及其他文章)。
另外,鲍勃在论坛的回答中还说:
窗口的所有权意味着它们将不受控制地闪烁,因为您无法在目标窗口区域之外进行双缓冲。 例如,带有子控件的面板不能对其本身及其子控件进行双缓冲。
正确执行此操作的唯一方法是创建一个单独的控件,该控件使用保留模式图形系统的形式来完成所有绘图。
因此,要使用手动双缓冲实现无闪烁文本框调整大小,您需要以某种方式将文本框渲染到后台缓冲区,然后将其显示为缓冲更新的一部分。如果可能的话:我不认为这会很容易。
[更新]
其他一些答案说这是 Windows 窗体的具体问题。这是不正确的,它实际上比这更深,并且是由 Windows GDI 引起的。例如,打开记事本/写字板等并粘贴一大块文本,调整窗口大小,并注意到相同的闪烁问题。
这是我几年前用来做类似事情的基本解决方案。它是一个简单的表单,包含一个多行文本框和一个继承自Panel 的自定义类。两个控件具有相同的位置和大小。它使用窗体 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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14554 次 |
| 最近记录: |