home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / MENU95.PAK / MENU.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  13.5 KB  |  484 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE: menu.c
  9. //
  10. //  PURPOSE: Handles messages and commands for simple menus
  11. //
  12. //
  13. //  FUNCTIONS:
  14. //    WndProc       - Processes messages for the main window.
  15. //    MsgCommand    - Handle the WM_COMMAND messages for the main window.
  16. //    MsgCreate     - Insert the states menu into the windows menu bar
  17. //    MsgPaint      - Places instructions for popup menu in main window.
  18. //    MsgDestroy    - Frees resources allocated by MsgCreate
  19. //    CmdStates     - Handle the States menu
  20. //    ShrinkBitmap  - Shrinks a 64x64 bitmap to checkmark size
  21. //    CreateStateMI - Sets up the MENUITEMINFO stucture and inserts the item
  22. //
  23. //  COMMENTS:
  24. //
  25. //
  26. //
  27. //   SPECIAL INSTRUCTIONS: N/A
  28. //
  29.  
  30. #include <windows.h>            // required for all Windows applications
  31. #include "globals.h"            // prototypes specific to this application
  32. #include "resource.h"
  33.  
  34. // Main window message table definition.
  35. MSD rgmsd[] =
  36. {
  37.     {WM_COMMAND,        MsgCommand},
  38.     {WM_DESTROY,        MsgDestroy},
  39.     {WM_CREATE,         MsgCreate},
  40.     {WM_MEASUREITEM,    MsgMeasureItem},
  41.     {WM_DRAWITEM,       MsgDrawItem},
  42.     {WM_RBUTTONUP,      MsgButtonUp},
  43.     {WM_PAINT,          MsgPaint}
  44. };
  45.  
  46. MSDI msdiMain =
  47. {
  48.     sizeof(rgmsd) / sizeof(MSD),
  49.     rgmsd,
  50.     edwpWindow
  51. };
  52.  
  53.  
  54. // Main window command table definition.
  55. CMD rgcmd[] =
  56. {
  57.     {IDM_STATE1,        CmdStates},
  58.     {IDM_STATE2,        CmdStates},
  59.     {IDM_STATE3,        CmdStates},
  60.     {IDM_STATE4,        CmdStates},
  61.     {IDM_BLACK,         CmdColors},
  62.     {IDM_RED,           CmdColors},
  63.     {IDM_BLUE,          CmdColors},
  64.     {IDM_GREEN,         CmdColors},
  65.     {IDM_COLOROWNERDR,  CmdColorOwnerDr},
  66.     {IDM_FONT,          CmdFont},
  67.     {IDM_SIZE,          CmdSize},
  68.     {IDM_STYLE,         CmdStyle},
  69.     {IDM_EXIT,          CmdExit}
  70. };
  71.  
  72. CMDI cmdiMain =
  73. {
  74.     sizeof(rgcmd) / sizeof(CMD),
  75.     rgcmd,
  76.     edwpWindow
  77. };
  78.  
  79.  
  80. HBITMAP ShrinkBitmap(HWND, HBITMAP);
  81. BOOL CreateStateMI(HWND, int, int, int, LPSTR, int);
  82.  
  83. HBITMAP  hbmpCheckOn;
  84. HBITMAP  hbmpCheckOff;
  85. HBITMAP  hbmpDot;
  86.  
  87. //
  88. //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
  89. //
  90. //  PURPOSE:  Processes messages for the main window.
  91. //
  92. //  PARAMETERS:
  93. //    hwnd     - window handle
  94. //    uMessage - message number
  95. //    wparam   - additional information (dependant on message number)
  96. //    lparam   - additional information (dependant on message number)
  97. //
  98. //  RETURN VALUE:
  99. //    The return value depends on the message number.  If the message
  100. //    is implemented in the message dispatch table, the return value is
  101. //    the value returned by the message handling function.  Otherwise,
  102. //    the return value is the value returned by the default window procedure.
  103. //
  104. //  COMMENTS:
  105. //    Call the DispMessage() function with the main window's message dispatch
  106. //    information (msdiMain) and the message specific information.
  107. //
  108.  
  109. LRESULT CALLBACK WndProc(HWND   hwnd, 
  110.                          UINT   uMessage, 
  111.                          WPARAM wparam, 
  112.                          LPARAM lparam)
  113. {
  114.     return DispMessage(&msdiMain, hwnd, uMessage, wparam, lparam);
  115. }
  116.  
  117.  
  118. //
  119. //  FUNCTION: MsgCommand(HWND, UINT, WPARAM, LPARAM)
  120. //
  121. //  PURPOSE: Handle the WM_COMMAND messages for the main window.
  122. //
  123. //  PARAMETERS:
  124. //    hwnd     - window handle
  125. //    uMessage - WM_COMMAND (Unused)
  126. //    GET_WM_COMMAND_ID(wparam, lparam)   - Command identifier
  127. //    GET_WM_COMMAND_HWND(wparam, lparam) - Control handle
  128. //
  129. //  RETURN VALUE:
  130. //    The return value depends on the message number.  If the message
  131. //    is implemented in the message dispatch table, the return value is
  132. //    the value returned by the message handling function.  Otherwise,
  133. //    the return value is the value returned by the default window procedure.
  134. //
  135. //  COMMENTS:
  136. //    Call the DispCommand() function with the main window's command dispatch
  137. //    information (cmdiMain) and the command specific information.
  138. //
  139.  
  140. #pragma argsused
  141. LRESULT MsgCommand(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  142. {
  143.     return DispCommand(&cmdiMain, hwnd, wparam, lparam);
  144. }
  145.  
  146.  
  147. //
  148. //  FUNCTION: MsgCreate(HWND, UINT, WPARAM, LPARAM)
  149. //
  150. //  PURPOSE: Insert the states menu into the windows menu bar.
  151. //
  152. //  PARAMETERS:
  153. //    hwnd      - Window handle
  154. //    uMessage  - WM_CREATE     (Unused)
  155. //    wparam    - Extra data    (Unused)
  156. //    lparam    - Extra data    (Unused)
  157. //
  158. //  RETURN VALUE:
  159. //     0 - Message handled - success
  160. //    -1 - Could not handle message - failure
  161. //
  162. //  COMMENTS: Creates a new (empty) menu and appends to it the "State"
  163. //    menu items. It sets up the user-defined checkmarks for the
  164. //    menu. It then inserts this menu into the main menu bar.
  165. //
  166.  
  167. #pragma argsused
  168. LRESULT MsgCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  169. {
  170.      MENUITEMINFO mii;
  171.     char    miStr[20];
  172.     HMENU   hmenu;
  173.     HMENU   hmenuWnd;
  174.  
  175.     // Create a new menu into the menubar on the fly.
  176.     hmenu = CreatePopupMenu();
  177.     if (hmenu == NULL)
  178.     {
  179.         // Return failure if the menu could not be created
  180.         return -1;
  181.     }
  182.  
  183.      // Set up the bitmaps for menu check states
  184.     hbmpCheckOn  = ShrinkBitmap(hwnd, LoadBitmap(hInst, "checkon"));
  185.     hbmpCheckOff = ShrinkBitmap(hwnd, LoadBitmap(hInst, "checkoff"));
  186.  
  187.     // Load the Menu item information structure and insert the menu item in 
  188.     // to the sub menu via CreateStateMI() helper function below.
  189.     if (!(CreateStateMI(hmenu, IDM_STATE1, 0, MFS_CHECKED, "South Dakota", 12)
  190.         &&
  191.           CreateStateMI(hmenu, IDM_STATE2, 1, MFS_UNCHECKED, "Washington", 10)
  192.         &&
  193.           CreateStateMI(hmenu, IDM_STATE3, 2, MFS_UNCHECKED, "California", 10)
  194.         &&
  195.           CreateStateMI(hmenu, IDM_STATE4, 3, MFS_UNCHECKED, "Oregon", 6)))
  196.      {
  197.         // If any of the insersions fail, destroy the menu and return failure
  198.        DestroyMenu(hmenu);
  199.        return -1;
  200.     }
  201.  
  202.  
  203.     // Set up the MENUITEMINFO for the "State" Menu
  204.     lstrcpy(miStr,"States");
  205.     mii.fMask         = MIIM_TYPE |           // The Mask determines which of
  206.                         MIIM_SUBMENU |        // he items will be set, Type
  207.                         MIIM_ID;              // (typedata,cch),ID & submenu
  208.     mii.fType         = MFT_STRING;           // MIIM_TYPE-> Type is set
  209.      mii.wID           = IDM_STATE;            // MIIM_ID-> ID is set
  210.     mii.hSubMenu      = hmenu;                // MIIM_SUBMENU-> hSubMenu is set
  211.     mii.dwTypeData    = (LPSTR)&miStr;        // MIIM_TYPE is MFT_STRING this 
  212.     mii.cch           = sizeof(miStr);        //    string and its size 
  213.     mii.cbSize        = sizeof(MENUITEMINFO); // Size of menu item structure
  214.  
  215.     // Now insert the menu into the main menu bar.
  216.     hmenuWnd = GetMenu (hwnd);
  217.     InsertMenuItem(hmenuWnd, 2, TRUE, &mii);
  218.  
  219.     // Load bitmap for custom menu
  220.     hbmpDot = LoadBitmap(hInst, "dot");
  221.  
  222.      return 0;
  223. }
  224.  
  225. //
  226. //  FUNCTION: MsgPaint(HWND, UINT, WPARAM, LPARAM)
  227. //
  228. //  PURPOSE: Places instructions for popup menu in main window.
  229. //
  230. //  PARAMETERS:
  231. //    hwnd      - Window handle
  232. //    uMessage  - WM_PAINT      (Unused)
  233. //    wparam    - Extra data    (Unused)
  234. //    lparam    - Extra data    (Unused)
  235. //
  236. //  RETURN VALUE:
  237. //    Always returns 0 - Message handled
  238. //
  239. //  COMMENTS:
  240. //
  241. //
  242.  
  243. #pragma argsused
  244. LRESULT MsgPaint(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  245. {
  246.      PAINTSTRUCT ps;
  247.     HDC hdc = BeginPaint(hwnd, &ps);
  248.     RECT rc;
  249.  
  250.     // Center the text in the client area
  251.     GetClientRect (hwnd, (LPRECT)&rc);
  252.     DrawText(hdc,
  253.              "Right click in this window for a popup menu",
  254.              -1,
  255.              (LPRECT)&rc,
  256.              DT_CENTER | DT_WORDBREAK);
  257.  
  258.     EndPaint(hwnd, &ps);
  259.  
  260.     return 0;
  261. }
  262.  
  263. //
  264. //  FUNCTION: MsgDestroy(HWND, UINT, WPARAM, LPARAM)
  265. //
  266. //  PURPOSE: Frees resources allocated by MsgCreate
  267. //
  268. //  PARAMETERS:
  269. //    hwnd      - Window handle (Unused)
  270. //    uMessage  - WM_DESTROY    (Unused)
  271. //    wparam    - Extra data    (Unused)
  272. //    lparam    - Extra data    (Unused)
  273. //
  274. //  RETURN VALUE:
  275. //
  276. //    Always returns 0 - Message handled
  277. //
  278. //  COMMENTS:
  279. //
  280. //
  281.  
  282. #pragma argsused
  283. LRESULT MsgDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  284. {
  285.      DeleteObject(hbmpCheckOn);
  286.      DeleteObject(hbmpCheckOff);
  287.      DeleteObject(hbmpDot);
  288.  
  289.      PostQuitMessage(0);
  290.  
  291.     return 0;
  292. }
  293.  
  294. //
  295. //  FUNCTION: CmdStates(HWND, WORD, WORD, HWND)
  296. //
  297. //  PURPOSE: Handle the States menu
  298. //
  299. //  PARAMETERS:
  300. //    hwnd      - Window handle
  301. //    wCommand  - IDM_STATEx
  302. //    wNotify   - Notification number (unused)
  303. //    hwndCtrl  - NULL.
  304. //
  305. //  RETURN VALUE:
  306. //
  307. //    Always returns 0 - Message handled
  308. //
  309. //  COMMENTS:
  310. //
  311. //
  312.  
  313. #pragma argsused
  314. LRESULT CmdStates(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  315. {
  316.      static UINT idmCur = IDM_STATE1;
  317.  
  318.      if ((UINT) wCommand != idmCur)
  319.      {
  320.           // Get the State Menu from the window
  321.           HMENU hmenu = GetSubMenu(GetMenu(hwnd), IDSTATES_POS);
  322.  
  323.           MENUITEMINFO mii;
  324.  
  325.           // Uncheck the currently selected item
  326.           mii.cbSize = sizeof(MENUITEMINFO);
  327.           mii.fMask = MIIM_STATE;
  328.           mii.fState = MFS_UNCHECKED;
  329.           SetMenuItemInfo(hmenu,idmCur,FALSE,&mii);
  330.  
  331.           // Check the newly checked item
  332.           mii.fState = MFS_CHECKED;
  333.           SetMenuItemInfo(hmenu,wCommand,FALSE,&mii);
  334.  
  335.           idmCur = (UINT)wCommand;
  336.     }
  337.  
  338.     return 0;
  339. }
  340.  
  341.  
  342. //
  343. //  FUNCTION: CmdExit(HWND, WORD, WORD, HWND)
  344. //
  345. //  PURPOSE: Exit the application.
  346. //
  347. //  PARAMETERS:
  348. //    hwnd - The window.
  349. //    wCommand - IDM_EXIT (unused)
  350. //    wNotify   - Notification number (unused)
  351. //    hwndCtrl - NULL (unused)
  352. //
  353. //  RETURN VALUE:
  354. //    Always returns 0 - command handled.
  355. //
  356. //  COMMENTS:
  357. //
  358. //
  359.  
  360. #pragma argsused
  361. LRESULT CmdExit(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  362. {
  363.     DestroyWindow(hwnd);
  364.     return 0;
  365. }
  366.  
  367.  
  368. //
  369. //  FUNCTION: ShrinkBitmap(HWND, HBITMAP)
  370. //
  371. //  PURPOSE: Shrinks a 64x64 bitmap to checkmark size
  372. //
  373. //  PARAMETERS:
  374. //    hwnd - The window used to get the DC
  375. //    hbmp - The 64x64 bitmap to shrink
  376. //
  377. //  RETURN VALUE:
  378. //
  379. //    A handle to 16x16 bitmap
  380. //
  381. //  COMMENTS:
  382. //    This function shrinks a 64x64 bitmap into a bitmap useable
  383. //    for the user-defined checkmark for menu items. This can be
  384. //    easily generalized to shrink bitmaps of any size.
  385. //
  386. //    This function deletes the original bitmap.
  387. //
  388.  
  389. HBITMAP ShrinkBitmap(HWND hwnd, HBITMAP hbmp)
  390. {
  391.     HDC     hdc;
  392.     HDC     hdcNew;
  393.     HDC     hdcOld;
  394.     LONG    checkMarkSize;
  395.     HBITMAP hbmpRet;
  396.     HBITMAP hbmpOld;
  397.     HBITMAP hbmpNew;
  398.  
  399.     hdc = GetDC(hwnd);
  400.  
  401.     // Create DCs for the source (old) and target (new) bitmaps
  402.     hdcNew = CreateCompatibleDC(hdc);
  403.     hdcOld = CreateCompatibleDC(hdc);
  404.  
  405.     // Determine the dimensions of the default menu checkmark and
  406.     // create a target bitmap of the same dimensions
  407.     checkMarkSize = GetMenuCheckMarkDimensions();
  408.     hbmpRet = CreateCompatibleBitmap(hdc,
  409.                                      LOWORD(checkMarkSize),
  410.                                      HIWORD(checkMarkSize));
  411.  
  412.     // Select the source bitmap and the target bitmap into their
  413.     // respective DCs.
  414.     hbmpOld = SelectObject(hdcNew, hbmpRet);
  415.     hbmpNew = SelectObject(hdcOld, hbmp);
  416.  
  417.     // Shrink the source bitmap into the target DC
  418.     if (!StretchBlt(hdcNew,
  419.                     0, 0,
  420.                     LOWORD(checkMarkSize),
  421.                     HIWORD(checkMarkSize),
  422.                     hdcOld,
  423.                     0, 0,
  424.                     64, 64,
  425.                     SRCCOPY))
  426.         hbmpRet = NULL;
  427.  
  428.     // De-select the bitmaps and clean up ..
  429.     SelectObject(hdcNew, hbmpOld);
  430.     SelectObject(hdcOld, hbmpNew);
  431.     DeleteDC(hdcNew);
  432.     DeleteDC(hdcOld);
  433.     DeleteObject(hbmp);
  434.     ReleaseDC(hwnd, hdc);
  435.  
  436.     // Return a handle to the target bitmap
  437.     return hbmpRet;
  438. }
  439.  
  440. //
  441. //  FUNCTION: CreateStateMI(HWND, int, int, int, LPSTR, int)
  442. //
  443. //  PURPOSE: Create a Submenu item for the State Menu by setting up the 
  444. //    MENYITEMINFO structure and calling InsertMenuItem().  
  445. //
  446. //  PARAMETERS:
  447. //    hMenu - Hanle of the submenu.
  448. //    miID  - Menu Item ID.
  449. //    Pos   - Position of the menu item.
  450. //    State - Menu Item State Checked(MFS_CHECKED) or Unchecked(MFS_UNCHECKED)
  451. //    lpmiStr - Menu item description string.
  452. //    SizeOfStr - Size of the menu item description string.
  453. //
  454. //  RETURN VALUE:
  455. //    BOOL - TRUE if InsertMenuItem was successful otherwise FALSE
  456. //
  457. //  COMMENTS:
  458. //
  459.  
  460. BOOL CreateStateMI(HWND hmenu,
  461.                    int miID,
  462.                    int pos,
  463.                    int state,
  464.                    LPSTR lpmiStr,
  465.                    int SizeOfStr)
  466. {
  467.     MENUITEMINFO mii;
  468.  
  469.     // Set up the MENUITEMINFO;
  470.     mii.fMask         = MIIM_TYPE | MIIM_STATE |
  471.                         MIIM_CHECKMARKS | MIIM_ID;
  472.     mii.fType         = MFT_STRING;
  473.     mii.fState        = state;
  474.     mii.wID           = miID;
  475.     mii.hSubMenu      = NULL;
  476.     mii.hbmpChecked   = hbmpCheckOn;
  477.     mii.hbmpUnchecked = hbmpCheckOff;
  478.     mii.dwTypeData    = lpmiStr;
  479.     mii.cch           = SizeOfStr;
  480.     mii.cbSize        = sizeof(MENUITEMINFO);
  481.  
  482.     return InsertMenuItem(hmenu,pos,TRUE,&mii);
  483. }
  484.