我的自定义绘图区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))
答案 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()
函数。但是,现在,我有更多的问题......但这将是另一个问题,使用一个独立的示例程序。