题
好的,所以在我的应用程序中,有一堆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的测试。您可以获得不同的结果。