c - BeginPaint() 不删除背景

标签 c winapi gdi

BeginPaint()文档说:

If the window's class has a background brush, BeginPaint uses that brush to erase the background of the update region before returning.

我是这样设置画笔的:

wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);

我在我的窗口上绘制了一个位图,然后我要求使用以下代码重绘:

RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW);

我在 WM_PAINT 中有这段代码:

case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        EndPaint(hWnd, &ps);
    }
    break;

所以我预计 BeginPaint() 会删除位图,但位图仍保留在窗口上!

我正在使用 Windows 7。

最佳答案

(将此写为答案,因为解释太长,无法发表评论)。

客户区的绘制可以在标准 Windows 模型中的两个地方完成:

WM_ERASEBKGND 名义上处理删除背景。 WM_PAINT 名义上处理在背景上绘制东西。

如果将 WM_ERASEBKGND 传递给 DefWindowProc,它将使用类画笔绘制背景。如果您想自己处理 WM_ERASEBKGND,您有两种选择:

  • 您可以自己删除背景,并返回 1(或任何非零值)
  • 可以不删除,返回0

如果你实现后一个选项,当你稍后收到一个WM_PAINT消息并调用BeginPaint时,fErase标志PAINTSTRUCT 将设置为 TRUE,表示背景仍被标记为删除。

BeginPaint 函数本身根本不进行任何绘画,它所做的只是为您提供一个可以绘画的 DC。当您调用 EndPaint 时,之前标记为脏的区域被“视为”已绘制(并删除)并且将不再标记为脏。

背景删除和前景绘画中的绘画划分(至少在我看来)是 16 位世界的残余,其中绘画是一项昂贵的操作。如果前景绘画也删除背景(例如,您正在绘制纯色 block 或纯色图像),那么将背景作为单独的步骤删除是浪费时间,并且通常会导致可见的闪烁。因此,根据您的应用程序,您可能希望完全忽略“删除背景”步骤 - 从 WM_ERASEBKGND 返回 0 并在 WM_PAINT 中绘制“背景”和前景”一步到位。

关于c - BeginPaint() 不删除背景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32112569/

相关文章:

c - 缓冲区与字符串比较(没有换行符)

windows - 是否可以在没有实际窗口的情况下在 Windows 操作系统上显示 "on screen"文本?

windows - 从 ReplaceFile 重现 ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 错误代码

c++ - 带有互斥锁和事件的 WaitForMultipleObjects

c++ - GDI+抖动问题

c++ - 使用 Direct2D 在非客户区绘制

c - K&R答题簿练习1.21

c - strcpy() 不写入新字符串

c++ - 字符数组类型转换为整数

c++ - 从 C++ 程序更改另一个程序的背景颜色