我有一个表单,在构造函数中设置了以下样式:
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
我在Paint
事件中绘制了一些矩形。表单上没有控件。然而,当我调整窗体大小时,窗体右侧和底部会出现黑色条纹。有没有办法摆脱它们?我已经尝试过所有方法,包括在WndProc
中监听WM_ERASEBKGND
,手动在WM_PAINT
中绘制窗体,实现自定义双缓冲等。还有其他什么方法可以尝试吗?
我找到了这个链接:https://connect.microsoft.com/VisualStudio/feedback/details/522441/custom-resizing-of-system-windows-window-flickers,看起来像是DWM的一个bug,但我希望能够找到一些解决方法。
请注意,我必须使用双缓冲,因为我想在Paint
事件中绘制相当复杂的图形展示。我使用C# .NET 2.0,在Win7上进行开发。
状态更新1
我通过自己实现调整大小功能成功地摆脱了大部分黑色条纹。然而,仍然存在一些小故障。有没有办法同时进行resize
和paint
操作?这是我需要做的伪代码:
IntPtr hDC;
var size = new Size(250, 200);
IntPtr handle = API.PaintAndResizeBegin(this.Handle /* Form.Handle */,
size.Width, size.Height, out hDC);
using (var g = Graphics.FromHdc(hDC)) {
this.backBuffer.Render(g, size);
}
API.PaintAndResizeCommit(handle);
有没有办法实现上述代码?
第二种解决方案是将整个表单(包括非客户端区域)进行后备缓冲。但是如何做到这一点呢?我不想自己绘制非客户端区域,因为我想保持Vista/7上的漂亮的aero效果。任何帮助将不胜感激。
状态更新2
看起来这个问题无法解决,因为它在Windows中无处不在,在每个应用程序中都存在。我们只能希望微软从Mac OS X中汲取灵感,在新的Windows中提供适当的API。
Resize
上执行重建,而不是ResizeEnd
,但这会有点慢,不如您所希望的那样平滑。对于这种性能,您不能使用GDI来进行繁重的工作(即使用Graphics或Bitmap类)。相反,使用硬件加速API(这就是MacOS和Vista/7用于平滑一切的方法)。对于.NET,请查看WPF(甚至XNA)。您可以通过它们获得完美流畅的渲染,并且您将获得0行代码的调整大小。 - Allon Guralnek