WM_PAINT 返回 0 导致 cpu 使用率 2%

Posted

技术标签:

【中文标题】WM_PAINT 返回 0 导致 cpu 使用率 2%【英文标题】:WM_PAINT return 0 causing cpu usage 2% 【发布时间】:2018-03-10 12:33:09 【问题描述】:

我的 WM_Paint 有问题

如果我让它返回 0/1,即使程序被最小化,我的 cpu 也会保持在 1% 左右。

我的绘图窗口正在使用 OpenGL

如果我从 WM_PAINT 中断,它会在调整大小时导致绘图问题

case WM_PAINT:

    application->paint_window();
    return 0;


window = std::make_unique<platform::window>(
    L"Main window",
    CW_USEDEFAULT, CW_USEDEFAULT,
    1200, 600,
    WS_OVERLAPPEDWINDOW /*| WS_CLIPSIBLINGS | WS_CLIPCHILDREN*/, 0,
    CS_OWNDC,
    this, process_message
);

while (::GetMessage(&msg, 0, 0, 0) > 0)

    if (!::TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    

编辑: 如果我在 WM_PAINT 中删除我的函数调用,我的 cpu 会上升到 15%。 如果我什么都不做,为什么它会这么高。

【问题讨论】:

只有 2%?这取决于你制作的程序类型,要么什么都没有,要么很少。 在窗口最小化并且不应该做任何事情时大约 2%,但由于某种原因仍然收到 WM_PAINT 消息 有一个非常简单的解决方案:当窗口最小化时不要绘画:)。在您的 WM_PAINT 处理程序中,检查窗口是否已最小化,在这种情况下不要绘制。 如果您没有在 WM_PAINT 事件处理程序中调用 Begin/EndPaint(),那么操作系统会认为窗口没有被绘制。所以它再次生成 WM_PAINT。您的 UI 线程将燃烧 100% 核心。所以在 6 核的机器上看到 15% 是正常的。如何调用你的函数可以降低它并不明显,但它可能做正确的事情。如果您不知道为什么您的程序需要太多 cpu,请使用分析器。顺便说一句。 听起来您在paint_window() 中有一个阻塞调用,等待GPU 完成渲染,从而限制了您调用GetMessage 的频率,最终限制了WM_PAINT 的调用频率消息到达。不过,如果没有看到该代码,这只是猜测。 【参考方案1】:

如the WM_PAINT message 中所述:

当窗口的更改改变了客户区的内容时,系统会将此消息发送到窗口过程。

系统保留一个内部更新区域来确定窗口的任何部分是否需要绘制。应用程序负责验证它已绘制到的区域(通过调用 BeginPaint、ValidateRect 或 ValidateRgn)。

未能验证不再需要更新的区域将使系统重新生成WM_PAINT 消息。这会导致您观察到的资源消耗。

【讨论】:

即使我在 opengl 上下文中绘图? @ciyaso:窗口子系统不知道您的 OpenGL 上下文。它将保持自己的无效区域概念,这可能与您的 OpenGL 上下文无关。如果您不希望窗口子系统继续生成WM_PAINT 消息,则必须遵守其规则,并验证无效区域。 @ciyaso:不过这很常见。使用窗口子系统进行可见性测试和更新管理,甚至使用 OpenGL 应用程序。您必须将窗口的更新区域转换为 OpenGL 场景,并将其传递给渲染引擎。它仍然需要您然后清除窗口系统看到的无效区域。这完全取决于应用程序的特性,这是否有用。

以上是关于WM_PAINT 返回 0 导致 cpu 使用率 2%的主要内容,如果未能解决你的问题,请参考以下文章

从 Windows7 中的安全屏幕 (Ctrl+Alt+Del) 返回时未收到 WM_PAINT 消息

VC SDK中关于WM_PAINT的新手问题

win32-gdi系统驱动的WM_PAINT无闪烁吗?

WM_PAINT与WM_ERASEBKGND

GDI 设备环境句柄

WCF双向调用:意外递归