【问题标题】:Drawing without flickering绘图不闪烁
【发布时间】:2026-01-16 10:10:01
【问题描述】:

我有一个用 c++ 开发的 win32 应用程序。该应用程序使用基本形状(矩形)在窗口上绘制一些东西。使用 InvalidateRect 每 20 毫秒(50 赫兹)重新绘制一次窗口。一切正常,但绘图闪烁。我怎样才能防止闪烁?在c#中我通常使用双缓冲组件(例如pictureBox),我怎么能在c++中使用win32摆脱这个?

【问题讨论】:

    标签: c++ winapi drawing flicker


    【解决方案1】:

    您可以创建一个内存中的设备上下文,将这些形状绘制到其中(就像您绘制窗口的设备上下文一样),然后在窗口无效时从它blit 到窗口的设备上下文。

    您还需要在抽签发生之前禁用背景清除(适当地处理 WM_ERASEBKGND 窗口消息)。

    编辑:我偶然发现了一个非常详尽的tutorial GDI 中无闪烁绘图,它解释了在 Windows 中绘图的所有方面并附带示例。

    【讨论】:

    【解决方案2】:

    您也可以在 Win32 中轻松实现双缓冲。假设您正在使用 Window 的设备上下文直接在 Window 上进行绘画,请改为执行以下操作:

    创建一个“内存”设备上下文并在该设备上下文上执行所有绘图,然后在适当时使用BitBlt() 函数将窗口的无效部分复制到实际设备上下文

    有一个很好的(虽然是高水平的)概述here.

    【讨论】:

    • 选择这个答案,因为它是唯一一个有例子的答案
    【解决方案3】:

    您也可以在 C++ 中使用双缓冲。

    当您获得要绘制的 DC 时,您会创建一个屏幕外位图 (CreateCompatibleBitmap) 和一个内存 DC (CreateCompatibleDC)。把你所有的画都交给那个 DC。最后,从内存 DC 到实际 DC 进行 BitBlt。

    为了提高性能,您可能希望缓存离屏位图和 DC,但请记住在窗口大小更改时重新创建它们。

    【讨论】:

      【解决方案4】:

      这是我发现的最棒的教程:

      https://msdn.microsoft.com/en-us/library/ms969905.aspx

      简而言之 - 是的,您必须实现双缓冲。它是通过创建内存中的 DC,然后使用该 DC 将您想要的所有内容绘制到内存中的位图来完成的,然后才将该位图提交给实际的 DC。

      【讨论】: