How to draw in the nonclient area?

17.8k Views Asked by At

I'd like to be able to do some drawing to the right of the menu bar, in the nonclient area of a window.

Is this possible, using C++ / MFC?

4

There are 4 best solutions below

0
On BEST ANSWER

Charlie hit on the answer with WM_NCPAINT. If you're using MFC, the code would look something like this:

// in the message map
ON_WM_NCPAINT()

// ...

void CMainFrame::OnNcPaint()
{
   // still want the menu to be drawn, so trigger default handler first
   Default();

   // get menu bar bounds
   MENUBARINFO menuInfo = {sizeof(MENUBARINFO)};
   if ( GetMenuBarInfo(OBJID_MENU, 0, &menuInfo) )
   {
      CRect windowBounds;
      GetWindowRect(&windowBounds);
      CRect menuBounds(menuInfo.rcBar);
      menuBounds.OffsetRect(-windowBounds.TopLeft());

      // horrible, horrible icon-drawing code. Don't use this. Seriously.
      CWindowDC dc(this);
      HICON appIcon = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
      ::DrawIconEx(dc, menuBounds.right-18, menuBounds.top+2, appIcon, 0,0, 0, NULL, DI_NORMAL);
      ::DestroyIcon(appIcon);
   }
}
0
On

In order to draw in the non-client area, you need to get the "window" DC (rather than "client" DC), and draw in the "window" DC.

0
On

If you just want something in the menu bar, maybe it is easier/cleaner to add it as a right-aligned menu item. This way it'll also work with different Windows themes, etc.

0
On

You should try handling WM_NCPAINT. This is similar to a normal WM_PAINT message, but deals with the entire window, rather than just the client area. The MSDN documents on WM_NCPAINT provide the following sample code:

case WM_NCPAINT:
{
 HDC hdc;
 hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
 // Paint into this DC
 ReleaseDC(hwnd, hdc);
}

This code is intended to be used in the message loop of your applicaton, which is canonically organized using a large 'switch' statement.

As noted in the MFC example from Shog, make sure to call the default version, which in this example would mean a call to DefWindowProc.