Search code examples
winapigdi

Can't draw in title bar on WM_NCPAINT?


I'm trying to draw something in the title bar area to represent an X since there is no WS_CAPTION, it just uses WS_EX_TOOLWINDOW | WS_EX_TOPMOST and WS_POPUP|WS_THICKFRAME. But I can't get anything to draw anywhere. I did a test below to just fill it all in red, but nothing changed. What am I doing wrong or missing?

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;
}

Solution

  • Based on a Link from Remy about the evil WM_NCPAINT, converted from the pascal version to the C++ version below. It works as well as the link in stackoverflow but again, only if WS_CAPTION is provided. I'm just posting here for completeness.

    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;
    }