Popup menu or context menus are those which generally appear when user right clicks on graphical widgets. These menus are aligned to the context of the child windows like edit menu for textbox, and graphical toolbox for graphic editors.

TrackPopupMenu() Win32 API is used to display a context menu in a specific position of the screen. This API takes a handle to a popup menu. We can load an popup menu from existing resource or we can create popup menu dynamically with CreatePopupMenu() Win32 call.

BOOL TrackPopupMenu(
        HMENU hMenu,         /* Handle to a popup menu */
        UINT uFlags,         /* flags for display menu */
        int x,               /* Absolute X co-ordinate in screen */
        int y,               /* Absolute Y co-ordinate in screen */
        int nReserved,       /* must be zero */
        HWND hWnd,           /* Handle to parent window */
        const RECT *prcRect  /* Optional*/
);
HMENU CreatePopupMenu(); /* Creates a new handle to popup menu */

Context/Popup menu example using TrackPopupMenu()

Source Code

#include <windows.h>
#include <stdio.h>

/* Context Menu IDs */
#define IDM_CONTEXT_LINE   1000
#define IDM_CONTEXT_RECTAN 1001
#define IDM_CONTEXT_CIRCLE 1002
#define IDM_CONTEXT_HELP   1003

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)"MyWin32Popup";


  RegisterClass(&wc);

   hWnd = CreateWindow("MyWin32Popup", "Popup/Context Menu", 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)
{
  char * context_menu[] = { "Line", "Rectangle", "Circle", "Help"};
  char msg[50];
  switch (message) 
  {
    case WM_COMMAND:
    {
      if(wParam >= IDM_CONTEXT_LINE && wParam <= IDM_CONTEXT_HELP) {
         sprintf(msg, "Clicked on %s", context_menu[wParam -IDM_CONTEXT_LINE]);
         MessageBox(hWnd, msg, "Popup Menu", MB_OK);
      }
      DefWindowProc(hWnd, message, wParam, lParam);
      break;
    }
    case WM_RBUTTONDOWN:
    {
      POINT pt;
      HMENU hMenuPopup = CreatePopupMenu();
      AppendMenu(hMenuPopup, MF_STRING, IDM_CONTEXT_LINE, "Line");
      AppendMenu(hMenuPopup, MF_STRING, IDM_CONTEXT_RECTAN, "Rectangle");
      AppendMenu(hMenuPopup, MF_STRING, IDM_CONTEXT_CIRCLE, "Circle");
      AppendMenu(hMenuPopup, MF_SEPARATOR, 0, NULL);
      AppendMenu(hMenuPopup, MF_STRING, IDM_CONTEXT_HELP, "Help");
      pt.x= GET_X_LPARAM(lParam);
      pt.y= GET_Y_LPARAM(lParam);
      ClientToScreen(hWnd, &pt);
      TrackPopupMenu(hMenuPopup, 
                     TPM_LEFTALIGN | TPM_RIGHTBUTTON, 
                     pt.x, pt.y, 0, hWnd, NULL);
      DestroyMenu(hMenuPopup);
      break;
    }
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

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 ...

#