【发布时间】:2011-10-26 12:21:44
【问题描述】:
可以使用GetDC/ReleaseDC在窗口的客户区绘制。但是为了响应 WM_PAINT 消息,必须使用 BeginPaint/EndPaint。这有什么特别之处吗?
【问题讨论】:
标签: c++ winapi gdi paint wm-paint
可以使用GetDC/ReleaseDC在窗口的客户区绘制。但是为了响应 WM_PAINT 消息,必须使用 BeginPaint/EndPaint。这有什么特别之处吗?
【问题讨论】:
标签: c++ winapi gdi paint wm-paint
当需要更新窗口的一部分时会发出 WM_PAINT 消息。 通过指定 BeginPaint/EndPaint() 你告诉 gdi 你实际上是在做那个工作。 如果您不为指定区域调用 BeginPaint(),WM_PAINT 消息将一直生成,直到有人实际更新它为止。该功能为您提供 DC 只是因为它很方便。在内部 BeginPaint()/EndPaint() 可能调用 GetDC()/ReleaseDC()。
与 GetDC 和 ReleaseDC 相比,您告诉 GDI您现在要在 DC 上绘制一些东西,而 gdi 没有要求您必须这样做。
【讨论】:
BeginPaint 不验证句柄,而是验证无效区域(通过调用 InvalidateRect/InvalidateRgn 标记为无效的区域)。这是告诉系统,无效区域已被重新绘制,不再需要绘制,直到窗口的某些部分再次失效。仅当无效区域非空时才会生成 WM_PAINT 消息。作为参考,您应该阅读About Painting and Drawing,并从那里获取。
是的,当然。 BeginPaint() 检索更新区域并自动处理再次清空它。如果您使用 GetDC(),那么您会注意到您的程序正在燃烧 100% cpu 内核,一遍又一遍地运行 WM_PAINT 处理程序,因为更新区域从未被清除。您必须调用 ValidateRect() 来避免这种情况。
【讨论】:
GetUpdateRgn 可以检索当前的更新区域,而ValidateRect(或ValidateRgn)可以用来验证一个矩形/区域。 BeginPaint 和 EndPaint 更简单。
BeginPaint API 调用验证更新区域(参见GetUpdateRgn:“BeginPaint 函数自动验证更新区域,因此对 GetUpdateRgn 的任何调用 在调用 BeginPaint 检索一个空的更新区域后立即进行。")。
BeginPaint function automatically sets the clipping region of the device context 因此,如果只需要重绘窗口的一部分,则不会重绘整个窗口。
【讨论】: