winapi:在WM_PAINT中使用bRepaint TRUE的GetUpdateRect()不清除绘制区域,但是WM_PAINT外面的InvalidateRect()呢?

时间:2014-04-11 01:20:45

标签: winapi go gdi

我的自定义绘图区WM_PAINT看起来像这样:

// TRUE to clear the background
if (GetUpdateRect(hwnd, &r, TRUE) == 0)
    return; // no update rect; do nothing
dc = BeginPaint(hwnd, &ps);
// check return
// paint some RGBA image data with GDI+
EndPaint(hwnd, &ps);

(暂时忽略向HDD +发送HDC。)

我在这里使用GetUpdateRect()而不是从BeginPaint()获取更新rect,因为我总是想要绘制一个空白画布,特别是因为我在这里进行了alpha混合绘图。此外,the docs for WM_PAINT表示如果BeginPaint()失败,则不要致电GetUpdateRect()

但是,当我的自定义绘图区域实际执行此WM_PAINT时,它不会清除绘图区域。我可以说,因为支持alpha的图像是在它自身的顶部绘制的,导致颜色较暗。

在我的代码的另一部分中,我通过调用InvalidateRect()来强制更新整个区域来响应键盘事件。如果我改变

的等价物
InvalidateRect(hwnd, NULL, FALSE);

InvalidateRect(hwnd, NULL, TRUE);

该区域确实正确清理。

那么我到底做错了什么呢?感谢。

(实际代码是this;它是用Go编写的。这也是我直接使用GDI +的原因。(我还没弄明白如何使用常规代码进行alpha混合GDI))

3 个答案:

答案 0 :(得分:1)

InvalidateRect使区域无效,这意味着它后面是擦除/重绘请求。您将它与不进行验证或失效的GetUpdateRect进行比较,并使用TRUE参数以与标准绘图擦除相同的方式擦除该区域。此外as MSDN states

  

BeginPaint函数检索的更新矩形与GetUpdateRect检索的更新矩形相同。

     

BeginPaint自动验证更新区域,因此在调用BeginPaint之后立即调用GetUpdateRect会检索一个空的更新区域。

总之,我没有看到任何理由在绘图处理程序中调用GetUpdateRect的方式。 BeginPaint以相同的方式进行验证,并且无论如何都需要在绘图处理程序中完成。一旦你在那里,就已经调用了erase handler,而不需要通过GetUpdateRect再次调用它。

BeginPaint的{​​{1}}以相同的方式获取更新区域,如果更新区域为空,则在调用PAINTSTRUCT::rcPaint之前不要执行任何操作。

答案 1 :(得分:0)

回复:

  

但是,当我的自定义绘图区域实际执行此WM_PAINT时,它不会清除绘图区域。我可以说,因为支持alpha的图像是在它自身的顶部绘制的,导致颜色较暗。

没有关于WM_PAINT或您调用的将清除该区域的函数。如果你想清除它,你必须自己做。大多数程序没有,因为清除后绘画会导致闪烁。如果您没有清除并且您确实绘制了透明对象,则表明您遇到了问题。解决方案可能是使用离屏绘图。

InvalidateRegion(,, true)不同。它将WM_ERASEBKGND和WM_NCPAINT消息发送到该区域进行擦除和绘制。

GDI不支持透明度。可以使用屏蔽操作模拟某些透明度。

GDI +引入了透明度支持,虽然用得不多,但相当广泛。将GDI +效果改造成遗留代码并不难,包括alpha通道PNG等。

Vista的奇特效果取决于DirectX,这是一个完全不同的绘图系统。 WPF中的Visual与旧DC非常不同。您可能需要考虑使用该系统编写新代码。

答案 2 :(得分:0)

感谢你们两位。 Stack Overflow只允许我一次授予一张支票......但是,在正确清理之后,我得到了检查答案中提到的闪烁。

最终我决定抛弃我到目前为止所做的事情,特别是在Treeki / Ninjifox的建议下,他建议我使用AlphaBlend()函数。但是,现在,我有更多的问题......但这将是另一个问题,使用一个独立的示例程序。