调整大小时带有巨大黑色闪烁的蒙皮 C# 表单!

发布于 2024-07-08 18:45:15 字数 430 浏览 10 评论 0原文

我正在尝试使用与您通常看到的不同的方法创建一些皮肤表单(仅边框和标题),但在调整表单大小时遇到​​表单闪烁的一些问题。

我不知道如何解释这个问题,所以这是我创建的一个视频来演示这个问题: http://www.screencast.com/t/AIqK9Szmz

另外,这是一个 VS2008 测试解决方案重新绘制表单边框的整个代码:http://stuff.nazgulled.net/misc/ TestForm.zip

希望有人能帮助我摆脱闪烁......

I'm trying to create some skinned forms (just the border and caption) with a different approach than you usually see but I'm having some issues with form flickering while I resize the form.

I don't know how else to explain the problem, so here's a video I created to demonstrate the problem:
http://www.screencast.com/t/AIqK9Szmz

Also, here's a VS2008 test solution with the whole code that repaints the form borders:http://stuff.nazgulled.net/misc/TestForm.zip

Hope someone can help me get rid of the flicker...

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

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

发布评论

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

评论(7

往昔成烟 2024-07-15 18:45:15

这就是我在基本表单的构造函数中使用的内容:

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

我认为关键是使用“AllPaintingInWmPaint”。

That's what I use in my base form's constructor:

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

I think the key is the use of "AllPaintingInWmPaint".

梨涡少年 2024-07-15 18:45:15

如果您想让表单具有不规则形状,则必须转向区域(如果您可以使用圆形和矩形等几何形状轻松定义表单区域)。 创建一个 System.Drawing.Graphics.Region 对象并向其添加形状。 我认为表单上的属性称为“区域” - 将您创建的区域分配给它。

您的另一个选择是使用分层窗口。 有人已经为您完成了所有工作< /a>. 分层窗口不适用于 2000 年之前的 Windows 版本,但它们具有半透明的额外好处。

您的最后一个选择是使用 WPF 并设置AllowsTransparency =“True”WindowStyle =“None”。 这将删除chrome(谷歌“chromeless window WPF”大约有一百万个例子)。

最后,如果您勇敢且有耐心,您总是可以捕获窗户后面的桌面并在其他任何事情之前将其绘制。 如果你的窗口移动,你将需要诉诸一些花哨的黑客技术:我真的不推荐这种方法 - 但你需要知道所有的选择。

If you want to make your form have a irregular shape you will have to turn to regions (if you can easily define your form's region using geometric shapes like Circle and Rectangle). Create a System.Drawing.Graphics.Region object and add shapes to it. I think the property on the form is called Region - assign to it your region that you created.

Your other option is to use layered windows. Somebody has done all the work for you. Layered windows do not work on versions of Windows older than 2000, but they have the added benefit of being semi-transparent.

Your final option is to use WPF and set AllowsTransparency="True" WindowStyle="None". That will remove the chrome (Google "chromeless window WPF" for like a million examples).

Finally if you are brave and patient you could always capture the desktop behind your window and paint it before anything else. You will need to resort to some fancy hackery if your window moves: I don't really recommend this approach - but you need to know all your options.

橘虞初梦 2024-07-15 18:45:15

(这是特定于 Vista 的解决方案;仅在启用桌面合成时才有效。)

看起来 Windows 通过将表单原始边框上的像素复制到新区域来初始化调整大小的表单的内容。 在您的情况下,新区域被初始化为黑色,可能是因为表单最初在其边框处有黑色像素。

要消除闪烁,只需将表单中最右边和最底下的像素行始终设置为 TransparencyKey - 这将使新区域保持透明,直到您有机会重新绘制它们。 即,将表格加宽 1 像素 & 比必要的高,并将多余的像素涂成透明。

示例: TransparentForm.zip

(This is a Vista-specific solution; it only works when desktop compositing is enabled.)

It looks like Windows initializes the contents of resized forms by copying the pixels on the form's original border over to the new areas. In your case, the new areas are initialized black likely because the form originally had black pixels at its border.

To get rid of the flickering, just keep the rightmost and bottommost line of pixels in the form always set to TransparencyKey -- this will keep the new areas transparent until you get a chance to repaint them. I.e., make the form 1 pixel wider & taller than necessary, and paint the extra pixels transparent.

Example: TransparentForm.zip

并安 2024-07-15 18:45:15

如果您想避免丑陋的未初始化黑色视频叠加闪烁,则必须放弃使用 Form.TransparencyKey 属性。 它在您的示例程序中没有做任何有用的事情。

You'll have to give up on using the Form.TransparencyKey property if you want to avoid the ugly uninitialized black video overlay flicker. It doesn't do anything useful in your sample program.

别低头,皇冠会掉 2024-07-15 18:45:15

尝试启用双缓冲?

Tried enabling DoubleBuffering ?

握住我的手 2024-07-15 18:45:15

哦,顺便说一句,除非您将所有绘制逻辑都放在 override OnPaint() 中,否则使用 SLIMcode 的代码将无法工作。 如果这听起来不熟悉,您可能不知道可以通过在表单上调用 Invalidate() 来强制要求重新绘制。 将代码重构为单个 Paint 方法是一项使命 - 但最终会产生更清晰的代码。

Oh, and by the way, using SLIMcode's code won't work unless you put all your paint logic in override OnPaint(). If this doesn't sound familiar you probably don't know that you can forcefully ask for a repaint by calling Invalidate() on your form. It's a mission to refactor your code into a single Paint method - but it results in cleaner code in the end.

与风相奔跑 2024-07-15 18:45:15

要在调整获胜表单大小时消除闪烁,请在调整大小时暂停布局。 重写表单 resizebegin/resizeend 方法,如下所示。

protected override void OnResizeBegin(EventArgs e) {
    SuspendLayout();
    base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
    ResumeLayout();
    base.OnResizeEnd(e);
}

这将使控件保持完整(与调整大小之前一样),并在调整大小操作完成时强制重绘。

To get rid of the flicker while resizing the win form, suspend the layout while resizing. Override the forms resizebegin/resizeend methods as below.

protected override void OnResizeBegin(EventArgs e) {
    SuspendLayout();
    base.OnResizeBegin(e);
}
protected override void OnResizeEnd(EventArgs e) {
    ResumeLayout();
    base.OnResizeEnd(e);
}

This will leave the controls intact (as they where before resizing) and force a redraw when the resize operation is completed.

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