home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c045 / 5.ddi / MENU / MENU.C$ / MENU.bin
Encoding:
Text File  |  1992-01-01  |  22.2 KB  |  656 lines

  1. /***************************************************************************
  2.  *                                                                         *
  3.  *  PROGRAM : Menu.c                                                       *
  4.  *                                                                         *
  5.  *  PURPOSE : To give a demonstration of the use of popup menus, user      *
  6.  *        defined menus and menu functions.                                *
  7.  *                                                                         *
  8.  *  FUNCTIONS   : WinMain()       - Calls the initialization function      *
  9.  *                  and enters the message loop.                           *
  10.  *                                                                         *
  11.  *        MenuInit()          - Registers the app. window class.           *
  12.  *                                                                         *
  13.  *        About()         - Dialog function for the About..                *
  14.  *                  dialog.                                                *
  15.  *                                                                         *
  16.  *        ShrinkBitmap()      - Shrinks a 64x64 bitmap to a size           *
  17.  *                  useable for a user-defined menu                        *
  18.  *                  checkmark.                                             *
  19.  *                                                                         *
  20.  *        HandleCreate()      - Creates a new menu and appends it          *
  21.  *                  to the main menu                                       *
  22.  *                                                                         *
  23.  *        HandlePaint()       - Handles repainting the app's client        *
  24.  *                  area                                                   *
  25.  *                                                                         *
  26.  *        HandleChangeColors()- Changes the state of the "colors"          *
  27.  *                  menu item.                                             *
  28.  *                                                                         *
  29.  *        HandleDrawItem()    - Redraws the menu items in the              *
  30.  *                  "colors" menu                                          *
  31.  *                                                                         *
  32.  *        HandlePopupMenu()   - handles display of the "floating"          *
  33.  *                  popup.                                                 *
  34.  *                                                                         *
  35.  *        MenuWndProc()       - Window function for the app.               *
  36.  *                                                                         *
  37.  *                                                                         *
  38.  ***************************************************************************/
  39. #include "windows.h"
  40. #include "menu.h"
  41.  
  42. HANDLE   hInst;
  43. HMENU    hBigMenu;
  44. HBITMAP  hbmCheckOn;
  45. HBITMAP  hbmCheckOff;
  46.  
  47. /****************************************************************************
  48.  *                                                                          *
  49.  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
  50.  *                                                                          *
  51.  *  PURPOSE    : Creates the main app. window, calls an initialization      *
  52.  *       function and enters the message loop.                              *
  53.  *                                                                          *
  54.  ****************************************************************************/
  55. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  56. {
  57.     HWND  hWnd;
  58.     MSG   msg;
  59.  
  60.     /* Register main window class if this is the first instance of the app. */
  61.     if (!hPrevInstance)
  62.         if (!MenuInit (hInstance))
  63.             return NULL;
  64.  
  65.     hInst = hInstance;
  66.  
  67.     /* Create the app. window */
  68.     hWnd = CreateWindow ("menu",
  69.              "Menu Example",
  70.              WS_OVERLAPPEDWINDOW,
  71.              CW_USEDEFAULT,
  72.              CW_USEDEFAULT,
  73.              CW_USEDEFAULT,
  74.              CW_USEDEFAULT,
  75.              (HWND) NULL,
  76.              NULL,
  77.              hInstance,
  78.              (LPSTR) NULL);
  79.  
  80.     if (!hWnd)
  81.         return NULL;
  82.  
  83.     ShowWindow (hWnd, nCmdShow);
  84.     UpdateWindow (hWnd);
  85.  
  86.     while (GetMessage (&msg, NULL, NULL, NULL)){
  87.     /* Since we have no accelerators, no need to call TranslateAccelerator here.*/
  88.         TranslateMessage (&msg);
  89.         DispatchMessage (&msg);
  90.     }
  91.     return(msg.wParam);
  92. }
  93.  
  94.  
  95. /****************************************************************************
  96.  *                                                                          *
  97.  *  FUNCTION   : MenuInit (hInstance)                                       *
  98.  *                                                                          *
  99.  *  PURPOSE    : Registers the main window class.                           *
  100.  *                                                                          *
  101.  *  RETURNS    : TRUE   -  if RegisterClass() went off ok                   *
  102.  *        FALSE  -  otherwise.                                              *
  103.  *                                                                          *
  104.  ****************************************************************************/
  105. BOOL NEAR PASCAL MenuInit (HANDLE hInstance)
  106. {
  107.     HANDLE    hMemory;
  108.     PWNDCLASS pWndClass;
  109.     BOOL      bSuccess;
  110.  
  111.     /* Initialize the menu window class */
  112.     hMemory   = LocalAlloc(LPTR, sizeof(WNDCLASS));
  113.     pWndClass = (PWNDCLASS) LocalLock(hMemory);
  114.  
  115.     pWndClass->style         = NULL;
  116.     pWndClass->lpfnWndProc   = MenuWndProc;
  117.     pWndClass->hInstance     = hInstance;
  118.     pWndClass->hIcon         = LoadIcon (hInstance, "menu");
  119.     pWndClass->hCursor       = LoadCursor (NULL, IDC_ARROW);
  120.     pWndClass->hbrBackground = GetStockObject (WHITE_BRUSH);
  121.     pWndClass->lpszMenuName  = (LPSTR) "MenuMenu",
  122.     pWndClass->lpszClassName = (LPSTR) "menu";
  123.  
  124.     bSuccess = RegisterClass (pWndClass);
  125.     LocalUnlock (hMemory);
  126.     LocalFree (hMemory);
  127.  
  128.     return bSuccess;
  129. }
  130.  
  131.  
  132. /****************************************************************************
  133.  *                                      *
  134.  *  FUNCTION   : About (hDlg, message, wParam, lParam)              *
  135.  *                                      *
  136.  *  PURPOSE    : Dialog function for the About menu... dialog.          *
  137.  *                                      *
  138.  ****************************************************************************/
  139. BOOL FAR PASCAL About(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  140. {
  141.     switch (message){
  142.     case WM_INITDIALOG:
  143.         return(TRUE);
  144.  
  145.     case WM_COMMAND:
  146.         if (wParam == IDOK)
  147.         {
  148.             EndDialog(hDlg,NULL);
  149.             return(TRUE);
  150.         }
  151.         break;
  152.     }
  153.     return(FALSE);
  154. }
  155.  
  156.  
  157. /****************************************************************************
  158.  *                                      *
  159.  *  FUNCTION   : ShrinkBitmap(hwnd, hbm)                    *
  160.  *                                      *
  161.  *  PURPOSE    : This function shrinks a 64x64 bitmap into a bitmap useable *
  162.  *       for the user-defined checkmark for menu items. This can be *
  163.  *       easily generalized to shrink bitmaps of any size.      *
  164.  *                                      *
  165.  *  RETURNS    : HBITMAP - A handle to the new bitmap.              *
  166.  *                                      *
  167.  ****************************************************************************/
  168. HBITMAP FAR PASCAL ShrinkBitmap (HWND hwnd, HBITMAP hbm)
  169. {
  170.     HDC     hdc;
  171.     HDC     hmemorydcNew;
  172.     HDC     hmemorydcOld;
  173.     LONG    checkMarkSize;
  174.     HBITMAP hCheckBitmap;
  175.     HBITMAP hOldBitmapSave;
  176.     HBITMAP hNewBitmapSave;
  177.  
  178.     hdc = GetDC (hwnd);
  179.  
  180.     /* Create DCs for the source (old) and target (new) bitmaps */
  181.     hmemorydcNew = CreateCompatibleDC (hdc);
  182.     hmemorydcOld = CreateCompatibleDC (hdc);
  183.  
  184.     /* Determine the dimensions of the default menu checkmark and
  185.      * create a target bitmap of the same dimensions
  186.      */
  187.     checkMarkSize = GetMenuCheckMarkDimensions ();
  188.     hCheckBitmap  = CreateCompatibleBitmap (hdc,
  189.                         LOWORD (checkMarkSize),
  190.                         HIWORD (checkMarkSize));
  191.  
  192.     /* Select the source bitmap and the target bitmap into their
  193.      * respective DCs.
  194.      */
  195.     hOldBitmapSave = SelectObject (hmemorydcNew, hCheckBitmap);
  196.     hNewBitmapSave = SelectObject (hmemorydcOld, hbm);
  197.  
  198.     /* Shrink the source bitmap into the target DC */
  199.     StretchBlt (hmemorydcNew,
  200.         0,
  201.         0,
  202.         LOWORD(checkMarkSize),
  203.         HIWORD(checkMarkSize),
  204.         hmemorydcOld,
  205.         0,
  206.         0,
  207.         64,
  208.         64,
  209.         SRCCOPY);
  210.  
  211.     /* De-select the bitmaps and clean up .. */
  212.     SelectObject (hmemorydcNew, hOldBitmapSave);
  213.     SelectObject (hmemorydcOld, hNewBitmapSave);
  214.     DeleteDC (hmemorydcNew);
  215.     DeleteDC (hmemorydcOld);
  216.     ReleaseDC (hwnd, hdc);
  217.  
  218.     /* .. and return a handle to the target bitmap */
  219.     return hCheckBitmap;
  220. }
  221.  
  222.  
  223. /****************************************************************************
  224.  *                                      *
  225.  *  FUNCTION   : HandleCreate ( hwnd )                      *
  226.  *                                      *
  227.  *  PURPOSE    : Creates a new (empty) menu and appends to it the "State"   *
  228.  *       menu items. It sets up the user-defined checkmarks for the *
  229.  *       menu. It then inserts this menu into the main menu bar.    *
  230.  *                                      *
  231.  ****************************************************************************/
  232. void FAR PASCAL HandleCreate (HWND hwnd)
  233. {
  234.     HMENU   hMenu;
  235.     HMENU   hWndMenu;
  236.     HBITMAP hbmOn;
  237.     HBITMAP hbmOff;
  238.  
  239.     /* Create a new menu into the menubar on the fly */
  240.     hMenu = CreateMenu ();
  241.     if (!hMenu)
  242.         return;
  243.  
  244.     /* Append the state menu items to it */
  245.     AppendMenu (hMenu, MF_STRING, IDM_STATE1, "South Dakota");
  246.     AppendMenu (hMenu, MF_STRING, IDM_STATE2, "Washington");
  247.     AppendMenu (hMenu, MF_STRING, IDM_STATE3, "California");
  248.     if (!AppendMenu (hMenu, MF_STRING, IDM_STATE4, "Oregon"))
  249.     {
  250.         /* It is unlikely the other appends will fail and this will succeed.
  251.         * So just check this one. And if it fails, Destroy the menu for
  252.         * good measure and return.
  253.         */
  254.         DestroyMenu(hMenu);
  255.         return;
  256.     }
  257.     hbmCheckOn  = ShrinkBitmap (hwnd, LoadBitmap (hInst, "checkon"));
  258.     hbmCheckOff = ShrinkBitmap (hwnd, LoadBitmap (hInst, "checkoff"));
  259.  
  260.     /* Set up the user-defined check marks */
  261.     SetMenuItemBitmaps (hMenu, 0, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
  262.     SetMenuItemBitmaps (hMenu, 1, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
  263.     SetMenuItemBitmaps (hMenu, 2, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
  264.     SetMenuItemBitmaps (hMenu, 3, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
  265.  
  266.     /* Now insert the menu into the main menu bar. */
  267.     hWndMenu = GetMenu (hwnd);
  268.     InsertMenu (hWndMenu, 2, MF_POPUP|MF_BYPOSITION, (WORD)hMenu, "States");
  269.  
  270.     return;
  271. }
  272.  
  273. /****************************************************************************
  274.  *                                      *
  275.  *  FUNCTION   : HandlePaint ( hwnd )                       *
  276.  *                                      *
  277.  *  PURPOSE    : Handles the repainting of the main app's client area.      *
  278.  *                                      *
  279.  ****************************************************************************/
  280. void FAR PASCAL HandlePaint (HWND hwnd)
  281. {
  282.     HDC     hdc;
  283.     PAINTSTRUCT ps;
  284.     RECT    rc;
  285.  
  286.     hdc = BeginPaint (hwnd, (LPPAINTSTRUCT)&ps);
  287.  
  288.     /* Center the text in the client area */
  289.     GetClientRect (hwnd, (LPRECT)&rc);
  290.     DrawText (hdc,
  291.           "Down click in the window for a popup menu",
  292.            41,
  293.            (LPRECT)&rc,
  294.            DT_CENTER | DT_WORDBREAK);
  295.     EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
  296. }
  297.  
  298.  
  299. /****************************************************************************
  300.  *                                      *
  301.  *  FUNCTION   : HandleChangeColors (hwnd)                  *
  302.  *                                      *
  303.  *  PURPOSE    : Toggles the state of the Owner Draw item in the Colors     *
  304.  *       menu. If it is on, the "Black", "Blue", "Red", and "Green" *
  305.  *               individual menu text items are modified so that they will  *
  306.  *       contain bands of color. Otherwise, the colors are replaced *
  307.  *       by the text.                                               *
  308.  *                                      *
  309.  ****************************************************************************/
  310. void FAR PASCAL HandleChangeColors(HWND hwnd)
  311. {
  312.     HMENU hMenu;
  313.     BOOL  fOwnerDraw;
  314.  
  315.     /* Get a handle to the Colors menu. This is at position 1. */
  316.     hMenu = GetSubMenu (GetMenu (hwnd), IDCOLORS_POS);
  317.  
  318.     /* Get the current state of the item */
  319.     fOwnerDraw = GetMenuState ( hMenu,
  320.                 IDM_COLOROWNERDR, MF_BYCOMMAND) & MF_CHECKED;
  321.  
  322.     /* Toggle the state of the item. */
  323.     CheckMenuItem ( hMenu,
  324.             IDM_COLOROWNERDR,
  325.             MF_BYCOMMAND | (fOwnerDraw ? MF_UNCHECKED : MF_CHECKED));
  326.  
  327.     if (!fOwnerDraw)
  328.     {
  329.     /* Change the items to owner-draw items. Pass the RGB value for the
  330.      * color as the application-supplied data. This makes it easier for
  331.      * us to draw the items.
  332.      */
  333.         ModifyMenu(hMenu,
  334.            IDM_BLACK,
  335.            MF_OWNERDRAW | MF_BYCOMMAND,
  336.            IDM_BLACK,
  337.            (LPSTR)RGB (0,0,0));
  338.  
  339.         ModifyMenu(hMenu,
  340.            IDM_BLUE,
  341.            MF_OWNERDRAW | MF_BYCOMMAND,
  342.            IDM_BLUE,
  343.            (LPSTR)RGB (0,0,255));
  344.  
  345.         ModifyMenu(hMenu,
  346.            IDM_RED,
  347.            MF_OWNERDRAW | MF_BYCOMMAND,
  348.            IDM_RED,
  349.            (LPSTR)RGB (255,0,0));
  350.  
  351.         ModifyMenu(hMenu,
  352.            IDM_GREEN,
  353.            MF_OWNERDRAW | MF_BYCOMMAND,
  354.            IDM_GREEN,
  355.            (LPSTR)RGB (0,255,0));
  356.     }
  357.     else
  358.     {
  359.         /* Change the items to normal text items. */
  360.         ModifyMenu(hMenu, IDM_BLACK, MF_BYCOMMAND, IDM_BLACK, "Black");
  361.         ModifyMenu(hMenu, IDM_BLUE, MF_BYCOMMAND, IDM_BLUE, "Blue");
  362.         ModifyMenu(hMenu, IDM_RED, MF_BYCOMMAND, IDM_RED, "Red");
  363.         ModifyMenu(hMenu, IDM_GREEN, MF_BYCOMMAND, IDM_GREEN, "Green");
  364.     }
  365. }
  366.  
  367.  
  368. /****************************************************************************
  369.  *                                      *
  370.  *  FUNCTION   : HandleDrawItem ( hwnd, lpdis)                  *
  371.  *                                      *
  372.  *  PURPOSE    : Called in response to a WM_DRAWITEM message, i.e. when the *
  373.  *       colors menu is being modified to an owner-draw menu, or    *
  374.  *       one of the items is selected. It sizes the checkmark bitmap*
  375.  *       to fit next to a color band and draws the color bands and  *
  376.  *       the checkmark on the popup menu.               *
  377.  *                                      *
  378.  ****************************************************************************/
  379. void FAR PASCAL HandleDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis)
  380. {
  381.     HDC     hdcBitmap;
  382.     HBITMAP hbmSave;
  383.     HBRUSH  hbr;
  384.     RECT    rc;
  385.     LONG    checkMarkSize;
  386.     DWORD   textColorSave;
  387.     DWORD   bkColorSave;
  388.  
  389.     /* Get the size of the checkmark so we can leave room for it since we
  390.      * want to be able to check the selected color.
  391.      */
  392.     checkMarkSize = GetMenuCheckMarkDimensions ();
  393.  
  394.     if (lpdis->itemAction == ODA_SELECT ||lpdis->itemAction == ODA_DRAWENTIRE)
  395.     {
  396.  
  397.  
  398.         CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
  399.         InflateRect ((LPRECT)&rc, (-2 - LOWORD(checkMarkSize)), -2);
  400.  
  401.         if (lpdis->itemState & ODS_SELECTED)
  402.         {
  403.             /* Item has been selected -- hilite with a gray frame */
  404.             hbr = GetStockObject (GRAY_BRUSH);
  405.             FrameRect (lpdis->hDC, (LPRECT)&rc, hbr);
  406.         }
  407.         else if (lpdis->itemAction == ODA_SELECT)
  408.         {
  409.             /* Item has been de-selected -- remove gray frame */
  410.             hbr = CreateSolidBrush (GetSysColor (COLOR_MENU));
  411.             FrameRect (lpdis->hDC, (LPRECT)&rc, hbr);
  412.             DeleteObject (hbr);
  413.         }
  414.     }
  415.  
  416.     if (lpdis->itemAction == ODA_DRAWENTIRE)
  417.     {
  418.  
  419.         /* Paint the color item in the color requested. */
  420.         hbr = CreateSolidBrush (lpdis->itemData);
  421.         CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
  422.         InflateRect ((LPRECT)&rc, -10-LOWORD(checkMarkSize), -10);
  423.         FillRect (lpdis->hDC, (LPRECT)&rc, hbr);
  424.         DeleteObject (hbr);
  425.  
  426.         if (lpdis->itemState & ODS_CHECKED)
  427.         {
  428.             /* Draw the check mark if the item is checked. */
  429.             hdcBitmap = CreateCompatibleDC (lpdis->hDC);
  430.             hbmSave = SelectObject (hdcBitmap, hbmCheckOn);
  431.  
  432.             textColorSave = SetTextColor (lpdis->hDC, 0x00000000L);
  433.             bkColorSave   = SetBkColor (lpdis->hDC, 0x00FFFFFFL);
  434.  
  435.             /* Use Magic bitblt op so that monochrome bitmaps preserve
  436.             background and foreground colors. */
  437.             BitBlt (lpdis->hDC,
  438.                 lpdis->rcItem.left,
  439.                 lpdis->rcItem.top+
  440.                 (MEASUREITEMHEIGHT - HIWORD (checkMarkSize)) / 2,
  441.                 LOWORD (checkMarkSize),
  442.                 HIWORD (checkMarkSize),
  443.                 hdcBitmap,
  444.                 0,
  445.                 0,
  446.                 ROP_PSDPxax);
  447.  
  448.             /* Restore colors and bitmap and clean up */
  449.             SetTextColor (lpdis->hDC, textColorSave);
  450.             SetBkColor (lpdis->hDC, bkColorSave);
  451.             SelectObject (hdcBitmap, hbmSave);
  452.             DeleteDC (hdcBitmap);
  453.         }
  454.     }
  455. }
  456.  
  457. /****************************************************************************
  458.  *                                      *
  459.  *  FUNCTION   : HandlePopupMenu (hwnd, point)                  *
  460.  *                                      *
  461.  *  PURPOSE    : Handles the display of the "floating" popup that appears   *                               *
  462.  *       on a mouse click in the app's client area.                 *
  463.  *                                      *
  464.  ****************************************************************************/
  465. void FAR PASCAL HandlePopupMenu (HWND hwnd, POINT point)
  466. {
  467.     HMENU hMenu;
  468.     HMENU hMenuTrackPopup;
  469.  
  470.     /* Get the menu for the popup from the resource file. */
  471.     hMenu = LoadMenu (hInst, "PopupMenu");
  472.     if (!hMenu)
  473.         return;
  474.  
  475.     /* Get the first menu in it which we will use for the call to
  476.      * TrackPopup(). This could also have been created on the fly using
  477.      * CreatePopupMenu and then we could have used InsertMenu() or
  478.      * AppendMenu.
  479.      */
  480.     hMenuTrackPopup = GetSubMenu (hMenu, 0);
  481.  
  482.     /* Convert the mouse point to screen coordinates since that is what
  483.      * TrackPopup expects.
  484.      */
  485.     ClientToScreen (hwnd, (LPPOINT)&point);
  486.  
  487.     /* Draw and track the "floating" popup */
  488.     TrackPopupMenu (hMenuTrackPopup, 0, point.x, point.y, 0, hwnd, NULL);
  489.  
  490.     /* Destroy the menu since were are done with it. */
  491.     DestroyMenu (hMenu);
  492. }
  493.  
  494. /****************************************************************************
  495.  *                                      *
  496.  *  FUNCTION   : MenuWndProc (hWnd, message, wParam, lParam)            *
  497.  *                                      *
  498.  *  PURPOSE    : Window function for the main app. window. Processes all the*
  499.  *       menu selections and oter messages.             *
  500.  *                                      *
  501.  ****************************************************************************/
  502. long FAR PASCAL MenuWndProc (HWND hWnd, unsigned message, WORD wParam, LONG lParam)
  503. {
  504.     FARPROC lpProc;
  505.     HMENU hMenu;
  506.     LPDRAWITEMSTRUCT dis;
  507.     RECT rc;
  508.  
  509.     switch (message){
  510.     case WM_SYSCOMMAND:
  511.         /* Show the About ... dialog */
  512.         if (wParam == ID_ABOUT)
  513.         {
  514.             lpProc = MakeProcInstance (About, hInst);
  515.             DialogBox (hInst,
  516.                 "AboutBox",
  517.                 hWnd,
  518.                 lpProc);
  519.  
  520.             FreeProcInstance (lpProc);
  521.             break;
  522.         }
  523.         else
  524.           return DefWindowProc (hWnd, message, wParam, lParam);
  525.  
  526.     case WM_COMMAND:
  527.         switch (wParam)
  528.         {
  529.             case IDM_EXIT:
  530.                 DestroyWindow (hWnd);
  531.             break;
  532.  
  533.             case IDM_ABOUT:
  534.                 /* Bring up the About.. dialog box */
  535.                 lpProc = MakeProcInstance (About, hInst);
  536.                 DialogBox (hInst,
  537.                     "AboutBox",
  538.                     hWnd,
  539.                     lpProc);
  540.  
  541.                 FreeProcInstance (lpProc);
  542.                 break;
  543.  
  544.             case IDM_COLOROWNERDR:
  545.                 /* Change colors in color menu depending on state of this
  546.                 menu item. */
  547.                 HandleChangeColors (hWnd);
  548.                 break;
  549.  
  550.             case IDM_STATE1:
  551.             case IDM_STATE2:
  552.             case IDM_STATE3:
  553.             case IDM_STATE4:
  554.                 /* Get a handle to the states menu... */
  555.                 hMenu = GetSubMenu (GetMenu (hWnd), IDSTATES_POS);
  556.  
  557.                 /* Uncheck all the items. */
  558.                 CheckMenuItem (hMenu, IDM_STATE1,MF_BYCOMMAND | MF_UNCHECKED);
  559.                 CheckMenuItem (hMenu, IDM_STATE2,MF_BYCOMMAND | MF_UNCHECKED);
  560.                 CheckMenuItem (hMenu, IDM_STATE3,MF_BYCOMMAND | MF_UNCHECKED);
  561.                 CheckMenuItem (hMenu, IDM_STATE4,MF_BYCOMMAND | MF_UNCHECKED);
  562.  
  563.                 /* ...and just check the selected one.*/
  564.                 CheckMenuItem (hMenu, wParam,MF_BYCOMMAND | MF_CHECKED);
  565.                 break;
  566.  
  567.             case IDM_BLACK:
  568.             case IDM_RED:
  569.             case IDM_BLUE:
  570.             case IDM_GREEN:
  571.                 /* Get a handle to the Colors menu. */
  572.                 hMenu = GetSubMenu (GetMenu (hWnd),IDCOLORS_POS);
  573.  
  574.                 /* Uncheck all the items. */
  575.                 CheckMenuItem (hMenu, IDM_BLACK, MF_BYCOMMAND | MF_UNCHECKED);
  576.                 CheckMenuItem (hMenu, IDM_RED, MF_BYCOMMAND | MF_UNCHECKED);
  577.                 CheckMenuItem (hMenu, IDM_BLUE, MF_BYCOMMAND | MF_UNCHECKED);
  578.                 CheckMenuItem (hMenu, IDM_GREEN,MF_BYCOMMAND | MF_UNCHECKED);
  579.  
  580.                 /* ...and just check the selected one.*/
  581.                 CheckMenuItem (hMenu, wParam,MF_BYCOMMAND | MF_CHECKED);
  582.                 break;
  583.  
  584.             case IDM_FONT:
  585.                 /* Messages sent to us from TrackPopupMenu when
  586.                 * items are selected from the "floating" popups
  587.                 */
  588.                 MessageBox (hWnd,"A font was selected","Popup Menu Alert",
  589.                     MB_APPLMODAL|MB_OK);
  590.                 break;
  591.  
  592.             case IDM_SIZE:
  593.                 MessageBox (hWnd,"A size was selected","Popup Menu Alert",
  594.                     MB_APPLMODAL|MB_OK);
  595.                 break;
  596.  
  597.             case IDM_STYLE:
  598.                 MessageBox (hWnd,"A style was selected","Popup Menu Alert",
  599.                     MB_APPLMODAL|MB_OK);
  600.                 break;
  601.         }
  602.         break;
  603.  
  604.     case WM_SIZE:
  605.         if (lParam)
  606.         {
  607.         /* If window is being sized to a non zero value...
  608.          * invalidate it's client area.
  609.          */
  610.             InvalidateRect (hWnd, NULL, TRUE);
  611.         }
  612.         break;
  613.  
  614.     case WM_PAINT:
  615.         HandlePaint (hWnd);
  616.         break;
  617.  
  618.     case WM_MEASUREITEM:
  619.         /* Use the same width for all items. We could examine the item id
  620.            and use different widths/heights for each item. */
  621.         ((LPMEASUREITEMSTRUCT)lParam)->itemWidth  = MEASUREITEMWIDTH;
  622.         ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = MEASUREITEMHEIGHT;
  623.         return TRUE;
  624.  
  625.     case WM_DRAWITEM:
  626.         /* Redraw the "colors" menu in normal/ownerdrawmode */
  627.         HandleDrawItem (hWnd,(LPDRAWITEMSTRUCT)lParam);
  628.         return TRUE;
  629.         break;
  630.  
  631.     case WM_CREATE:
  632.         /* Create the menu */
  633.         HandleCreate (hWnd);
  634.         break;
  635.  
  636.     case WM_DESTROY:
  637.         /* Delete the on/off bitmaps so that they don't waste memory. */
  638.         DeleteObject (hbmCheckOn);
  639.         DeleteObject (hbmCheckOff);
  640.  
  641.         PostQuitMessage (0);
  642.         break;
  643.  
  644.     case WM_LBUTTONDOWN:
  645.         /* Draw the "floating" popup in the app's client area */
  646.         GetClientRect (hWnd, (LPRECT)&rc);
  647.         if (PtInRect ((LPRECT)&rc, MAKEPOINT (lParam)))
  648.         HandlePopupMenu (hWnd, MAKEPOINT(lParam));
  649.         break;
  650.  
  651.     default:
  652.         return DefWindowProc(hWnd, message, wParam, lParam);
  653.     }
  654.     return(NULL);
  655. }
  656.