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