无法在 WM_NCPAINT 上的标题栏中绘制?

Can't draw in title bar on WM_NCPAINT?

我试图在标题栏区域绘制一些东西来表示 X,因为没有 WS_CAPTION,它只使用 WS_EX_TOOLWINDOW | WS_EX_TOPMOSTWS_POPUP|WS_THICKFRAME。但是我无法在任何地方画任何东西。我在下面做了一个测试,把它全部填成红色,但没有任何改变。我做错了什么或遗漏了什么?

case WM_NCACTIVATE:
case WM_NCPAINT:
{
  // call default handler (I've tried it both ways, with and without DefWindowProc)
  ::DefWindowProc(hwnd, umsg, wparam, lparam);
  HDC hdc;
  if ((hdc=::GetWindowDC(hwnd))!=NULL) { 
    // Paint into this DC 
    RECT rcwin;
    if (::GetWindowRect(hwnd, &rcwin)) {
      HBRUSH hbrush=::CreateSolidBrush(RGB(255, 0, 0));
      if (hbrush) {
        rcwin.right-=rcwin.left;
        rcwin.bottom-=rcwin.top;
        rcwin.left=rcwin.top=0;
        ::FillRect(hdc, &rcwin, hbrush);
        ::DeleteObject(hbrush);
      }
    }
    ::ReleaseDC(hwnd, hdc);
  }
  return 0;
}

不要直接在WM_NCACTIVATE中绘制。如果你需要触发重绘,你可以使用 RedrawWindow() 。在 WM_PAINT/WM_NCPAINT.

中完成所有实际绘图

WM_NCPAINT中绘图时,documentation says to use GetDCEx() to get the HDC to draw on. The wParam is an HRGN that you can draw within. You can use GetRgnBox()获取HRGN的外接矩形,如果需要的话。

case WM_NCPAINT: {
    ::DefWindowProc(hwnd, umsg, wparam, lparam);
    HRGN hrgn = (HRGN)wParam;
    HDC hdc = ::GetDCEx(hwnd, hrgn, DCX_WINDOW | DCX_INTERSECTRGN);
    HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
    ::FillRgn(hdc, hrgn, hbrush);
    ::DeleteObject(hbrush);
    ::ReleaseDC(hwnd, hdc);
    return 0;
}

基于 Remy 的 Link 关于邪恶 WM_NCPAINT 的文章,从 pascal 版本转换为下面的 C++ 版本。它与 Whosebug 中的 link 一样有效,但同样,仅当提供 WS_CAPTION 时。我只是为了完整性而在这里发帖。

case WM_NCPAINT:
{
    #ifndef DCX_USESTYLE
      #define DCX_USESTYLE 0x00010000
    #endif

  HDC hdc=::GetDCEx(hwnd, 0, DCX_WINDOW|DCX_USESTYLE);
  if (hdc) {
    RECT rcclient;
    ::GetClientRect(hwnd, &rcclient);
    RECT rcwin;
    ::GetWindowRect(hwnd, &rcwin);
    POINT ptupleft;
    ptupleft.x=rcwin.left;
    ptupleft.y=rcwin.top;
    ::MapWindowPoints(0, hwnd, (LPPOINT) &rcwin, (sizeof(RECT)/sizeof(POINT)));
    ::OffsetRect(&rcclient, -rcwin.left, -rcwin.top);
    ::OffsetRect(&rcwin, -rcwin.left, -rcwin.top);

    HRGN rgntemp=NULL;
    if (wparam==NULLREGION || wparam==ERROR) {
      ::ExcludeClipRect(hdc, rcclient.left, rcclient.top, rcclient.right, rcclient.bottom);
    }
    else {
      rgntemp=::CreateRectRgn(rcclient.left+ptupleft.x, rcclient.top+ptupleft.y, rcclient.right+ptupleft.x, rcclient.bottom+ptupleft.y);
      if (::CombineRgn(rgntemp, (HRGN) wparam, rgntemp, RGN_DIFF)==NULLREGION) {
         // nothing to paint
      }
      ::OffsetRgn(rgntemp, -ptupleft.x, -ptupleft.y);
      ::ExtSelectClipRgn(hdc, rgntemp, RGN_AND);
    }

    HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 0, 0));
    ::FillRect(hdc, &rcwin, hbrush);
    ::DeleteObject(hbrush);

    ::ReleaseDC(hwnd, hdc);
    if (rgntemp!=0) {
      ::DeleteObject(rgntemp);
    }
  }
  return 0;
}