如何设置受到闪烁影响的窗体控件的受保护的DoubleBuffered
属性?
public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
//Taxes: Remote Desktop Connection and painting
//http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
if (System.Windows.Forms.SystemInformation.TerminalServerSession)
return;
System.Reflection.PropertyInfo aProp =
typeof(System.Windows.Forms.Control).GetProperty(
"DoubleBuffered",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(c, true, null);
}
请查看此帖子,重申其中的核心答案:您可以在窗口上启用WS_EX_COMPOSITED样式标志,以使表单及其所有控件都具有双缓冲功能。该样式标志自XP以来可用。这并不会使绘画速度更快,但整个窗口会在屏幕外缓冲区中绘制,并在一次操作中复制到屏幕上。这使得用户无法看到任何视觉绘制瑕疵而呈现出即时效果。然而,它并非完全没有问题,某些视觉样式渲染器可能会出现故障,特别是当TabControl拥有过多选项卡时。结果因人而异。
将此代码粘贴到您的表单类中:
protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
这种技术与Winform的双缓冲支持之间的最大区别在于,Winform的版本仅适用于一个控件。您仍将看到每个单独的控件绘制自己。如果未绘制的控件矩形与窗口背景对比度很大,这可能会看起来像闪烁效果。System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control)
.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
aProp.SetValue(ListView1, true, null);
Ian在终端服务器上使用这个功能时提供了更多信息。
public void EnableDoubleBuffering()
{
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
一种方法是扩展您想要双缓冲的特定控件,并在控件的构造函数中设置DoubleBuffered属性。
例如:
class Foo : Panel
{
public Foo() { DoubleBuffered = true; }
}
nobugz 在他的链接中提出了这种方法,我只是转载。将此覆盖添加到表单:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
对我而言,这是最好的解决方法,在Windows 7上,当我调整一个控件密集型的表单时,会出现大块黑色区域。现在,控件会反弹!但是这样更好。
扩展方法:用于控制缓冲开关的双重缓冲
public static class ControlExtentions
{
/// <summary>
/// Turn on or off control double buffering (Dirty hack!)
/// </summary>
/// <param name="control">Control to operate</param>
/// <param name="setting">true to turn on double buffering</param>
public static void MakeDoubleBuffered(this Control control, bool setting)
{
Type controlType = control.GetType();
PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(control, setting, null);
}
}
使用方法(例如如何使DataGridView双缓冲):
DataGridView _grid = new DataGridView();
// ...
_grid.MakeDoubleBuffered(true);
这是一个优秀解决方案的VB.NET版本....:
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H2000000
Return cp
End Get
End Property
在尝试双缓冲之前,请尝试使用SuspendLayout()/ResumeLayout()解决您的问题。
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
最近我调整/重绘一个包含多个控件的控件时,出现了很多空洞(残留物)。
我尝试过WS_EX_COMPOSITED和WM_SETREDRAW,但是直到我使用了以下方法才解决了问题:
private void myPanel_SizeChanged(object sender, EventArgs e)
{
Application.DoEvents();
}
我想转达一下。
TEXTBOX
жҺ§д»¶дёҚйҒөеҫӘд»»дҪ•з»ҳ画规еҲҷпјҢеӣ жӯӨеҮәзҺ°дәҶиҝҷз§Қжғ…еҶөгҖӮ - Ian BoydTextBox
,请使用DetectUrls
设置为False的RichTextBox
。如果您希望它是可编辑的,请使用EM_SETCHARFORMAT和EM_SETPARAFORMAT消息剥离格式(示例代码在此处)。 - alldayremixTerminalServerSession
是一个异常情况,在运行时应该特别注意吗? - Gregor y