3

我有一个表单,它在构造函数中设置这些样式:

this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

我在Paint事件中画了一些矩形。表单上没有控件。但是,当我调整表格大小时,表格的右侧和底部都有黑色条纹。有没有办法摆脱它们?我已经尝试了一切,听WM_ERASEBKGNDin WndProc,手动绘制表单WM_PAINT,实现自定义双缓冲区等。还有什么我可以尝试的吗?

我发现了这个: https ://connect.microsoft.com/VisualStudio/feedback/details/522441/custom-resizing-of-system-windows-window-flickers 看起来它是 DWM 中的一个错误,但我只是希望我能做一些解决方法。

请注意,我必须使用双缓冲,因为我想在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 上保持良好的航空效果。任何帮助将不胜感激。

状态更新 2

看起来这个问题是无法解决的,因为它在 Windows 上无处不在,在每个应用程序中。我们只能希望 MS 在 Mac OS X 中获得一些灵感,并在新的 Windows 中提供适当的 API。

4

2 回答 2

1

我找到了可以同时绘制和调整窗口大小的功能 - UpdateLayeredWindow

所以现在应该可以创建可调整大小的窗口,这些窗口在调整大小时没有任何条带。但是,您需要自己绘制窗口内容,因此有点不方便。但我认为使用WPFandUpdateLayeredWindow应该没有任何问题。


更新

发现问题。:-) 使用时UpdateLayeredWindow,您必须自己绘制窗口的边框。所以,如果你想UpdateLayeredWindow在win7中使用漂亮的玻璃效果绘制标准窗口,你就完蛋了。

Microsft Connect上甚至有一个关于这个问题的线程,微软说这是一个设计错误,如果它得到修复,那么可能在 Win8 或一些更新的系统中。所以我们对此无能为力。

于 2010-06-21T17:36:00.223 回答
0

我发现最好不要直接在 Form 表面上进行任何自定义渲染。相反,在窗体上放置一个停靠的 PictureBox,创建将显示在 PictureBox 中的 Bitmap 对象,使用该System.Drawing.Graphics.FromImage(Image)方法将所有内容绘制到该对象上。

我使用该方法和游戏循环制作了一个简单的射击游戏(Crimsonland 风格),并获得了相当不错的性能(使用抗锯齿线),超过 100 FPS。

于 2010-04-26T08:55:22.140 回答