Client Area

Total area of a window is divided in two parts client area and non-client area. Client area of a window is the square area of window below title bar where user can place child widgets.

Non-Client Area

Not client area is the area of a window where operating system constructs borders, title bar, menu bar, minimize/maximize button and exit button etc. Non client area is generally under control of operating system and depending on the themes selected by user it changes its appearance.

Client area and Non-Client Area

GetDC () API returns the device context of the client area of the window. Where as GetWindowDC () returns the total area of the window including non-client area. To draw only in client area we should use device context returned by GetDC(). To draw in client or non-client area we should use device context returned by GetWindowDC(). GetDC() and GetWindowDC() function reference has been listed below for your reference.

GetDC()

GetDC() function retrieves a handle to a display device context for the client area of a specified window or for the entire screen. You can use the returned handle in subsequent GDI functions to draw in the device context.

HDC GetDC(
  HWND hWnd   /* handle to a window */
);

GetDC() Client Area drawing

This is an example using API GetDC(). We need to open winver app in Windows which display an about box. Here we find the handle of the window using FindWindow(). We have used GetDC to get the device contect of the client area and we are drawing a rectangle around the edges of this area.

#include <windows.h>
int main(int argc, char* argv[])
{
  HWND hWnd;
  HDC hDC;
  RECT rect;
  int dc;
  hWnd = FindWindow(NULL,"About Windows");
  printf("About Window handle %x\n", hWnd);
  if(hWnd != 0)
  {
    HBRUSH hB;
    LOGBRUSH lb;
    lb.lbColor = 0;
    lb.lbStyle = BS_NULL;
    lb.lbHatch = 0;

       hDC = GetDC(hWnd);
       dc = SaveDC(hDC);
     GetClientRect(hWnd, &rect);

     SelectObject(hDC, CreatePen(PS_SOLID, 4, RGB(0,255,0)));
     
     hB = CreateBrushIndirect(&lb);
     SelectObject(hDC, hB);
     Rectangle(hDC, 0, 0, 
       rect.right-rect.left , rect.bottom-rect.top);
     RestoreDC(hDC, dc);
     ReleaseDC(hWnd, hDC);
  }
  return 0;
}

Client Area drawing output

Client area drawing using GetDC()

GetWindowDC()

GetWindowDC() function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars. A window device context permits painting anywhere in a window, because the origin of the device context is the upper-left corner of the window instead of the client area. GetWindowDC assigns default attributes to the window device context each time it retrieves the device context. Previous attributes are lost.

HDC GetWindowDC(
  HWND hWnd   /* handle of window */
);

GetWindowDC() non client Area drawing

This is an example using API GetWindowDC() and Window event WE_NCPAINT. We have used GetWindowDC to get the device contect of the non client area and we are drawing a rectangle around the edges of this area.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd,
                         UINT message, 
                         WPARAM wParam,
                         LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  WNDCLASS wc;
  MSG msg;
  HWND hWnd;
  ZeroMemory(&wc, sizeof(WNDCLASS));

  wc.style           = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc     = (WNDPROC)WndProc;
  wc.hInstance       = hInstance;
  wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground   = (HBRUSH)(COLOR_BACKGROUND);
  wc.lpszClassName   = (LPCTSTR)"NonClientWin32Class";


  RegisterClass(&wc);

   hWnd = CreateWindow("NonClientWin32Class", "WM_NCPAINT event demo", WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  while (GetMessage(&msg, NULL, 0, 0)) 
  {
    DispatchMessage(&msg);
  }
  return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  PAINTSTRUCT ps;
  HDC hDC;
  RECT rect;
  int dc;
  HBRUSH hB;
  LOGBRUSH lb;

  switch (message) 
  {
    case WM_PAINT:
  {
      hDC = BeginPaint(hWnd, &ps);
    GetClientRect(hWnd, &rect);
      SetBkMode(hDC, TRANSPARENT);
    DrawText(hDC, "WM_NCPAINT event demo!", 22, &rect, DT_CENTER);
    EndPaint(hWnd, &ps);
    break;
  }
  case WM_NCPAINT:
  {
    DefWindowProc(hWnd, message, wParam, lParam);

    lb.lbColor = 0;
    lb.lbStyle = BS_NULL;
    lb.lbHatch = 0;

       hDC = GetWindowDC(hWnd);
       dc = SaveDC(hDC);
     GetWindowRect(hWnd, &rect);

     SelectObject(hDC, CreatePen(PS_SOLID, 4, RGB(0,255,0)));
     
     hB = CreateBrushIndirect(&lb);
     SelectObject(hDC, hB);
     Rectangle(hDC, 0, 0, 
       rect.right-rect.left , rect.bottom-rect.top);
     RestoreDC(hDC, dc);
     ReleaseDC(hWnd, hDC);
     break;
            
  }

    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

Client Area drawing output

Non Client area drawing using GetWindowDC() and WM_NCPAINT

You may also like to know : #WinMain #WNDCLASS #RegisterClass #CreateWindow #Window Proc #GetMessage & DispatchMessage #WPARAM & LPARAM #DefWindowProc #Device Context #PEN #BRUSH #WM_PAINT #SaveDC RestoreDC #GetDC ReleaseDC #Mouse Events

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

Learn on Youtube

#