好的,所以在我的应用程序中,有一堆Winapi和一些自定义控件。耶...

现在,通常,他们只会悄悄地重新绘制自己的动画,状态改变,ECT ....这一切都很好。

但是我有一种称为fix()的类窗口的方法。每当需要更新整个窗口时,这都是称为的。它调整控件的大小并使窗口无效。

当发生这种情况时,绘制了背景,然后将其绘制为选项卡控件,然后将所有其他内容都放在顶部。这会引起非常刺激的眨眼,尤其是在调整窗口大小时(由于fix()的持续调用)。

我尝试了什么:

  • ws_ex_composited。这只会使单个控件双重颠覆。这是一个改进,但闪烁不可避免地仍然存在。
  • 关闭背景图。几乎无法解决问题,实际上使事情变得更糟。

因此:我需要一种技术/方法/任何东西,才能使我整体延误窗口。我认为自己处理WM_PAINT消息可能是一个解决方案,但我不知道从哪里开始。我有一种可怕的感觉,这甚至不可能...

请帮助,这是一个关键问题。解决这个愚蠢的小问题时,我会感到非常放心。

有帮助吗?

解决方案

正是在这个时候,人们意识到Microsofts的深度无视本机开发人员。实际上,人们可以开始怀有微软故意破坏本地绘画的偏执妄想,以迫使本地开发人员搬到WPF。

首先,考虑 WS_EX_COMPOSITED. WS_EX_COMPOSITED 似乎是芥末: - 它说,它强制执行Botton来为儿童控件涂上油漆订单,并且基本上WM_PAINT消息会在批处理中处理。它说它是在Windows 2000(5.0)中添加的,并且向下几行,它不适用于启用桌面组合物。即,除非关闭空气玻璃,否则它会停止使用Windows Vista(6.0)工作?

然后,有两个可能的“黑客”试图让Fremer Freefer Painting工作:

  • 首先,您需要模仿过多的量。 WS_EX_CLIPCHILDREN | WS_EX_CLIPSIBLINGS 对于确保窗口的任何特定区域仅绘制一次。 BeginDeferWindowPos 也必须进行调整大小操作,以确保瞬态状态(一个窗口重叠另一个窗口)不会发生(即,在调整窗口A时,窗口B却没有)。

当然,当您尝试绘制皮肤对话框,使用组框或选项卡控件或其他数量的其他限制时, WS_EX_CLIPSIBLINGS 只是不合适。

  • WM_SETREDRAW 是一个神奇的信息。没有API可以访问此功能: WM_SETREDRAW 直接由DefwindowProc处理,以实质上将窗口标记为隐藏的持续时间。后 WM_SETREDRAW, FALSE 被发送,使用父窗口句柄(及其所有孩子)将返回不会在屏幕上绘制的DC,拨打GETDC/GETDCEX/GETWINDOWDC等。这使您有机会向孩子窗户做各种各样的事情,当您完成时,请发送 WM_SETREDRAW,TRUE, ,(然后手动重新粉刷窗口)。当然,所有子窗口都会在自己的时间里绘画,并且父窗口完成其擦除背景之后,因此WM_SETREDRAW不是灵丹妙药。

破裂后 WS_EX_COMPOSITED, ,在.NET的Winforms和WPF中,从头开始编写了控件,以不使用本机控件,因此他们可以在那里烘烤缓冲的绘画。和alpha也支持。

其他提示

嗯。在人们冲入并以重复的方式关闭此主题之前,我最好提到您的问题本身不是双重缓冲,而是在重新定位控件时闪烁,“手动”双重缓冲只是几种解决方案之一。

可能是 BeginDeferWindowPos &朋友可以修复闪烁。

免责声明:我曾经知道Win16 API的所有细节,但是自从我做了API级编程以来已经有几年了。

欢呼和hth。

- Alf

没有代码,我几乎无法想象实际情况是什么……但是您可以尝试处理WM_ERASEBKND,每当收到它们跳过擦除时,返回true。

处理 WM_ERASEBKGND 对于您的窗口和实现,排除了每个孩子控制的矩 true。对于所有其他儿童控制措施,都可以执行同样的操作,这些控件又具有其他控件(例如TAB控件)。

这里 对于使用MFC的示例。

在.net中有 ControlStyle.AllPaintingInWmPaint 应该在每个容器窗口(因此主窗口和标签)上设置。我找不到同等的Winapi。但是,这是将背景的绘画从wm_erasebkgnd移动到wm_paint。它还从父母那里减去子控制区域以避免闪烁,可能是您需要手动执行此操作。

我很惊讶WS_EX_COMPOSITED无济于事。如果您将其设置在顶级窗口上,并且请勿在子控件上拨打Redrawwindow,则应使用。

另请确保进行有或没有DWM/Aero的测试。您可以获得不同的结果。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top