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