调整窗口大小会导致出现黑条

发布于 2024-08-28 08:20:37 字数 1612 浏览 6 评论 0原文

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

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 中的一个错误,但我只是希望我能做一些解决方法。

请注意,我必须使用双缓冲,因为我想在 Paint 事件中绘制非常强烈的图形表示。我使用C# .NET 2.0、Win7进行开发。

状态更新 1

我已经通过自己实现调整大小功能成功消除了大部分黑色条纹。然而,仍然存在一些小故障。有没有办法同时进行resizepaint操作?这是我需要做的伪代码

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 上保持良好的空气动力学效果。任何帮助将不胜感激。

Status Update 2

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

I have a form, which sets these styles in constructor:

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

And I draw some rectangles in Paint event. There are no controls on the form. Hovewer, when I resize the form, there are black strips at right and bottom of the form. Is there any way to get rid of them? I've tried everything, listening for WM_ERASEBKGND in WndProc, manually drawing the form on WM_PAINT, implementing custom double buffer, etc. Is there anything else I could try?

I've found this:
https://connect.microsoft.com/VisualStudio/feedback/details/522441/custom-resizing-of-system-windows-window-flickers
and it looks like it is a bug in DWM, but I just hope I can do some workaround.

Please note that I must use double buffering, since I want to draw pretty intense graphic presentation in the Paint event. I develop in C# .NET 2.0, Win7.

Status Update 1

I've managed to get rid of most of the black stripes by implementing the resize functionality by myself. Hovewer there are still some minor glitches. Is there any way to do resize and paint operation at once? Here is a pseudo-code of what I need to do:

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);

Is there any way to implement the above code?

The second solution could be to back-buffer whole form, including non-client area. But how to do that? I don't want to paint the non-client area by myself, as I want to keep the nice aero effect on Vista/7. Any help will be deeply appreciated.

Status Update 2

It looks like this problem is unsolvable, since it is omnipresent on Windows, in every application. We can just hope that MS will take some inspiration in Mac OS X and will provide appropriate APIs in new Windows.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寒江雪… 2024-09-04 08:20:37

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

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


更新

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

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

I've found the function which can paint and resize window at the same time - UpdateLayeredWindow.

So now it should be possible to create resizable windows, which do not have any strips while being resized. However, you need to paint the window content yourself, so it is a little inconvenient. But I think that using WPF and UpdateLayeredWindow, there shouldn't be any problem.


Update

Found problems. :-) When using UpdateLayeredWindow, you must paint the window's border yourself. So, if you want standard window painted using UpdateLayeredWindow with nice glass effect in win7, you are screwed.

On Microsft Connect is even a thread about this problem, where Microsoft says it is a bug by design, and if it ever gets fixed, then probably in Win8 or some newer system. So there isn't much we could do about this.

东走西顾 2024-09-04 08:20:37

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

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

I found that it is best not to do any custom rendering directly on the Form surface. Instead, put a docked PictureBox on the form, create Bitmap object that will be displayed in the PictureBox, draw everything onto that using the System.Drawing.Graphics.FromImage(Image) method.

I used that method with a game loop to make a simple shooter game (Crimsonland-style) and got pretty good performance (with anti-aliased lines), above 100 FPS.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文