我正在尝试使用与您通常看到的不同的方法创建一些蒙皮表单(只是边框和标题),但是在调整表单大小时我遇到了表单闪烁的一些问题。
我不知道如何解释这个问题,所以这是我创建的一个视频来演示这个问题: http ://www.screencast.com/t/AIqK9Szmz
此外,这是一个 VS2008 测试解决方案,其中包含重新绘制表单边框的整个代码:http: //stuff.nazgulled.net/misc/TestForm.zip
希望有人能帮助我摆脱闪烁...
我正在尝试使用与您通常看到的不同的方法创建一些蒙皮表单(只是边框和标题),但是在调整表单大小时我遇到了表单闪烁的一些问题。
我不知道如何解释这个问题,所以这是我创建的一个视频来演示这个问题: http ://www.screencast.com/t/AIqK9Szmz
此外,这是一个 VS2008 测试解决方案,其中包含重新绘制表单边框的整个代码:http: //stuff.nazgulled.net/misc/TestForm.zip
希望有人能帮助我摆脱闪烁...
这就是我在基本表单的构造函数中使用的:
this.SetStyle( ControlStyles.AllPaintingInWmPaint, true );
this.SetStyle( ControlStyles.UserPaint, true );
this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );
this.SetStyle( ControlStyles.ResizeRedraw, true );
我认为关键是使用“AllPaintingInWmPaint”。
如果您想让您的表单具有不规则的形状,您将不得不转向区域(如果您可以使用圆形和矩形等几何形状轻松定义表单的区域)。创建一个 System.Drawing.Graphics.Region 对象并向其添加形状。我认为表单上的属性称为区域 - 将您创建的区域分配给它。
您的另一个选择是使用分层窗口。有人为你做了所有的工作。分层窗口不适用于早于 2000 的 Windows 版本,但它们具有半透明的额外好处。
您的最终选择是使用 WPF 并设置 AllowsTransparency="True" WindowStyle="None"。这将删除铬(谷歌“无铬窗口 WPF”,例如一百万个示例)。
最后,如果您勇敢且有耐心,您总是可以在窗口后面捕捉桌面并在其他任何事情之前对其进行绘制。如果您的窗口移动,您将需要求助于一些花哨的黑客:我并不真正推荐这种方法 - 但您需要知道所有选项。
(这是一个特定于 Vista 的解决方案;它仅在启用桌面合成时才有效。)
看起来 Windows 通过将表单原始边框上的像素复制到新区域来初始化调整大小的表单的内容。在您的情况下,新区域可能被初始化为黑色,因为表单最初在其边界处具有黑色像素。
要消除闪烁,只需将表单中最右边和最底部的像素线始终设置为 TransparencyKey - 这将使新区域保持透明,直到您有机会重新绘制它们。即,使表格比必要的宽和高 1 个像素,并将多余的像素涂成透明的。
如果您想避免丑陋的未初始化黑色视频覆盖闪烁,您将不得不放弃使用 Form.TransparencyKey 属性。它在您的示例程序中没有任何用处。
尝试启用双缓冲?
哦,顺便说一句,除非你把所有的绘制逻辑都放在 override OnPaint() 中,否则使用 SLIMcode 的代码是行不通的。如果这听起来不熟悉,您可能不知道您可以通过在表单上调用 Invalidate() 来强制要求重绘。将您的代码重构为一个单一的 Paint 方法是一项任务——但它最终会产生更清晰的代码。
要在调整 win 表单大小时消除闪烁,请在调整大小时暂停布局。覆盖表单 resizebegin/resizeend 方法,如下所示。
protected override void OnResizeBegin(EventArgs e) {
SuspendLayout();
base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
ResumeLayout();
base.OnResizeEnd(e);
}
这将使控件保持不变(与调整大小之前一样)并在调整大小操作完成时强制重绘。