【问题标题】:Is there something special about using BeginPaint/EndPain and not GetDC/ReleaseDC in response to WM_PAINT message?使用 BeginPaint/EndPain 而不是 GetDC/ReleaseDC 来响应 WM_PAINT 消息有什么特别之处吗?
【发布时间】:2011-10-26 12:21:44
【问题描述】:

可以使用GetDC/ReleaseDC在窗口的客户区绘制。但是为了响应 WM_PAINT 消息,必须使用 BeginPaint/EndPaint。这有什么特别之处吗?

【问题讨论】:

    标签: c++ winapi gdi paint wm-paint


    【解决方案1】:

    当需要更新窗口的一部分时会发出 WM_PAINT 消息。 通过指定 BeginPaint/EndPaint() 你告诉 gdi 你实际上是在做那个工作。 如果您不为指定区域调用 BeginPaint(),WM_PAINT 消息将一直生成,直到有人实际更新它为止。该功能为您提供 DC 只是因为它很方便。在内部 BeginPaint()/EndPaint() 可能调用 GetDC()/ReleaseDC()。

    与 GetDC 和 ReleaseDC 相比,您告诉 GDI现在要在 DC 上绘制一些东西,而 gdi 没有要求您必须这样做。

    【讨论】:

    • 那么BeginPaint返回的DC可能每次都不一样?这是否意味着重新绘制屏幕的某些部分并不是为了验证 DC 的句柄?无论如何,你能推荐一些关于这个的阅读吗?我觉得 MSDN 在这个话题上不能令人满意。
    • @stupid_idiot: BeginPaint 不验证句柄,而是验证无效区域(通过调用 InvalidateRect/InvalidateRgn 标记为无效的区域)。这是告诉系统,无效区域已被重新绘制,不再需要绘制,直到窗口的某些部分再次失效。仅当无效区域非空时才会生成 WM_PAINT 消息。作为参考,您应该阅读About Painting and Drawing,并从那里获取。
    • 这个答案缺少一个重要方面:BeginPaint“设置设备上下文的剪辑区域以排除更新区域之外的任何区域。” (正如elevener's answer 中指出的那样)。
    【解决方案2】:

    是的,当然。 BeginPaint() 检索更新区域并自动处理再次清空它。如果您使用 GetDC(),那么您会注意到您的程序正在燃烧 100% cpu 内核,一遍又一遍地运行 WM_PAINT 处理程序,因为更新区域从未被清除。您必须调用 ValidateRect() 来避免这种情况。

    【讨论】:

    • 嗯,实际上GetUpdateRgn 可以检索当前的更新区域,而ValidateRect(或ValidateRgn)可以用来验证一个矩形/区域。 BeginPaintEndPaint 更简单。
    • BeginPaint API 调用验证更新区域(参见GetUpdateRgnBeginPaint 函数自动验证更新区域,因此对 GetUpdateRgn 的任何调用 在调用 BeginPaint 检索一个空的更新区域后立即进行。")。
    【解决方案3】:

    BeginPaint function automatically sets the clipping region of the device context 因此,如果只需要重绘窗口的一部分,则不会重绘整个窗口。

    【讨论】:

    • 谢谢大家的回答,真的很难决定哪一个是最好的!
    猜你喜欢
    • 2019-01-11
    • 2011-08-16
    • 2016-07-02
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 2023-03-08
    • 2010-09-11
    • 2013-05-11
    相关资源
    最近更新 更多