【问题标题】:Behavior of WS_CLIPCHILDREN and InvalidateRect in Windows 7Windows 7 中 WS_CLIPCHILDREN 和 InvalidateRect 的行为
【发布时间】:2026-02-14 12:00:01
【问题描述】:

为了减少闪烁,我使用 WS_CLIPCHILDREN 标志创建父窗口,并在 WM_SIZE 事件期间调用 InvalidateRect。这种方法在 Windows XP 中运行良好。但是,我最近开始在 Windows 7 上编程,现在在调整窗口大小时遇到​​了渲染问题。调整窗口大小时,其内容不会刷新,直到我执行强制重绘的操作,例如最小化和恢复窗口。

我已尝试使用 UpdateWindow 调用跟进 InvalidateRect,但没有任何效果。

有谁知道正确的做法吗?

更新
我找到了解决方法:致电InvalidateRect(childHWND, NULL, FALSE) 在所有子窗口上加上 InvalidateRect(parentHWND, NULL, TRUE) 在父窗口上修复渲染问题,而不会引入明显的闪烁。

仍然欢迎其他建议!

更新 2
我尝试了RedrawWindow(hwnd, 0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN),但这导致了一些渲染问题(剩余像素)。

更新 3
RedrawWindow 后跟InvalidateRect(hwnd, NULL, TRUE) 时有效。谢谢@interjay!

【问题讨论】:

  • 我希望 Microsoft 的某个人能够发布一个清晰、简洁、如何调整大小且不闪烁且与其所有版本的操作系统兼容的方法!
  • 我已经编辑了我的答案并进行了修复。如果您再次回复我,请在我的答案下添加评论,否则我可能不会看到它。

标签: c++ winapi


【解决方案1】:

您可以尝试调用RedrawWindow,传递标志RDW_INVALIDATERDW_ALLCHILDREN

编辑

要重绘背景,可以添加 RDW_ERASE。如果要重绘父背景而不是子背景,请同时调用RedrawWindowInvalidateRect(...,TRUE)

【讨论】:

    【解决方案2】:

    我也遇到过类似的问题。 我查看了这个解决方案,但最后我想出了以下内容:

    void WindowClass::Invalidate(BOOL bErase)
    {
        base::Invalidate(bErase);
    
        // traverse along all the child windows.
        for (CWnd* pChild = GetWindow(GW_CHILD); pChild != NULL; pChild = pChild->GetWindow(GW_HWNDNEXT))
        {
            // Let them do the invalidate also.
            pChild->Invalidate(bErase);
        }
    }
    

    我希望这会有所帮助。 . .

    【讨论】:

      【解决方案3】:

      我最近在浏览其他内容时在某处发现了这个 sn-p - 它表明通过从 WNDCLASS 中删除 CS_VREDRAWCS_HREDRAW对于您的窗口,它会减少调整窗口大小时创建的工件。

      我使用以下 sn-p 来实现这一点,但我不能说我实际上注意到它有多少真正的影响:

      BOOL CMainFrame::PreCreateWindow(CREATESTRUCT & cs)
      {
          // do standard thing
          if (!CMFCToolboxMDIFrameWnd::PreCreateWindow(cs))
              return FALSE;
      
          // ensure a thinner border
          cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
      
          // avoid repainting when resized by changing the class style
          WNDCLASS wc;
          VERIFY(GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wc));
          cs.lpszClass = AfxRegisterWndClass(0, wc.hCursor, wc.hbrBackground, wc.hIcon);
      
          return TRUE;
      }
      

      【讨论】: