代码之家  ›  专栏  ›  技术社区  ›  Alexander Rafferty

双缓冲winAPI

  •  5
  • Alexander Rafferty  · 技术社区  · 15 年前

    现在,正常情况下,他们只会悄悄地为动画、状态改变等重新绘制自己。。。。一切都很好。

    但是我有一个名为fix()的类窗口方法。每当需要更新整个窗口时都会调用此函数。它调整控件的大小并使窗口无效。

    发生这种情况时,将绘制背景,然后绘制选项卡控件,然后绘制顶部的所有其他控件。这会导致非常恼人的闪烁,特别是在调整窗口大小时(因为对fix()的不断调用)。

    我试过的:

    • WS_EX_合成。这只会对单个控件进行双重缓冲。这是一个进步,但闪烁不可避免地仍然存在。
    • 关闭背景绘图。很难解决问题,反而使事情更糟。

    所以:我需要一种技术/方法/任何东西来允许我对整个窗口进行双重缓冲。我想自己处理WM_PAINT消息可能是一个解决方案,但我不知道从哪里开始。我有一种可怕的感觉这根本不可能。。。

    5 回复  |  直到 15 年前
        1
  •  5
  •   Chris Becke    15 年前

    首先,考虑 WS_EX_COMPOSITED . 合成的 似乎是芥末:它说它强制执行了一个从botton到top的子控件绘制顺序,基本上WM_paint消息是成批处理的。它说是在Windows2000中添加的(5.0条)而且,几行下来,它不工作与桌面合成启用。即。从Windows Vista开始停止工作(6.0条),除非关闭空气玻璃,否则谁会这么做?

    • 首先,你需要尽量减少过度上漆的数量。 WS_EX_CLIPCHILDREN | WS_EX_CLIPSIBLINGS 必须确保车窗的任何特定区域只喷漆一次。 BeginDeferWindowPos 还需要成批调整大小操作,以确保不会发生暂时状态(其中一个窗口与另一个窗口重叠)(即,当窗口A已调整大小,但窗口B尚未调整)。

    当然,当您试图绘制蒙皮对话框、使用组框、选项卡控件或任何其他限制时, WS_EX_CLIPSIBLINGS 只是不合适。

    • WM_SETREDRAW WM_SETREDRAW公司 由DefWindowProc直接处理,基本上将窗口标记为在持续时间内隐藏。之后 WM_SETREDRAW, FALSE 发送后,使用父窗口句柄(及其所有子窗口句柄)调用GetDC/GetDCEx/GetWindowDC etc将返回一个不会在屏幕上绘制的DC。这给了你一个机会去做各种各样的事情,当你完成了发送一个 WM_SETREDRAW,TRUE ,(然后手动重新绘制窗口)。当然,所有的子窗口都会在自己的时间内绘制,并且在父窗口完成背景的擦除之后,因此WM_SETREDRAW并不是一种灵丹妙药。

    合成的

        2
  •  1
  •   Cheers and hth. - Alf    15 年前

    可能是这样。 BeginDeferWindowPos

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

    干杯。,

    阿尔夫

        3
  •  0
  •   YeenFei    15 年前

    但您可以尝试处理WM_ERASEBKGND,当您收到它们时返回TRUE以跳过擦除。

        4
  •  0
  •   Hemant    15 年前

    WM_ERASEBKGND true .

    here 例如使用MFC。

        5
  •  0
  •   user180326 user180326    15 年前

    在.net中 ControlStyle.AllPaintingInWmPaint 它还从父控件中减去子控件的区域以避免闪烁,这可能是您需要手动执行此操作。

    我很惊讶WS_EX_COMPOSITED没有帮助。如果您在顶层窗口上设置了该选项,并且在子控件上不调用RedrawWindow,则该选项应该有效。