BeginPaint() 不擦除背景

BeginPaint() not erasing the background

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);

我在 Window 上绘制了位图,然后使用以下代码要求重绘:

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() 会擦除位图,但位图仍保留在 Window!

我正在使用 Windows 7.

(写这个作为答案,因为解释太长,无法评论)。

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

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

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

  • 您可以自己擦除背景,并且return 1(或任何非零值)
  • 可以不擦除,return0

如果您实施后一个选项,当您稍后收到 WM_PAINT 消息并调用 BeginPaint 时,PAINTSTRUCTfErase 标志将设置为 TRUE,说明背景还是被标记为擦除。

BeginPaint函数本身根本不做任何绘画,它所做的只是给你一个可以绘画的DC。当您调用 EndPaint 时,之前标记为脏的区域 "deemed" 已被绘制(并擦除)并且将不再被标记为脏。

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