|
|
1.1 ! root 1: /* This is a document showing Menus.c commented with PM information. */ ! 2: /* Menus.c is a combination of many of the menu functionality */ ! 3: /* available under PM. It shows cascaded menus, how to disable a */ ! 4: /* menu item through its attributes, how to check menu items through */ ! 5: /* their attributes, how to display bitmaps in menus, how to create */ ! 6: /* popup menus, how to change menus on the fly, and how to create new */ ! 7: /* menu items on the fly. */ ! 8: ! 9: #define INCL_WINMESSAGEMGR ! 10: #define INCL_WIN ! 11: #define INCL_GPI ! 12: #define INCL_WINDIALOGS ! 13: #include <os2.h> ! 14: #include "menus.h" ! 15: ! 16: #include "string.h" ! 17: #include "stdio.h" ! 18: #include "stdlib.h" ! 19: ! 20: MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM); ! 21: ! 22: int main (void) ! 23: { ! 24: static CHAR szClientClass [] = "menus"; ! 25: static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU | ! 26: FCF_SIZEBORDER | FCF_MINMAX | ! 27: FCF_SHELLPOSITION | FCF_TASKLIST | ! 28: FCF_MENU | FCF_ACCELTABLE ; ! 29: HAB hab; ! 30: HMQ hmq; ! 31: HWND hwndFrame, hwndClient; ! 32: QMSG qmsg; ! 33: ! 34: hab = WinInitialize (0); ! 35: hmq = WinCreateMsgQueue (hab, 0); ! 36: ! 37: WinRegisterClass ( ! 38: hab, // Anchor Block handle ! 39: szClientClass, // Name of class being registered ! 40: ClientWndProc, // Window procedure for class ! 41: CS_SIZEREDRAW, // Class style ! 42: 0); // Extra bytes to reserve ! 43: ! 44: hwndFrame = WinCreateStdWindow ( ! 45: HWND_DESKTOP, // Parent of Window handle ! 46: WS_VISIBLE, // Style of frame window ! 47: &flFrameFlags, // Pointer to control data ! 48: szClientClass, // Client window class name ! 49: NULL, // Title bar text ! 50: 0L, // Style of Client Window ! 51: 0, // Module of handle for resources ! 52: ID_RESOURCE, // ID of resources ! 53: &hwndClient); // Pointer to client window handle ! 54: ! 55: WinSendMsg (hwndFrame, WM_SETICON, ! 56: WinQuerySysPointer (HWND_DESKTOP, SPTR_APPICON, FALSE), ! 57: NULL); ! 58: ! 59: WinSetWindowText (hwndFrame, "Menus Code for PM Apps"); ! 60: ! 61: ! 62: while (WinGetMsg (hab, &qmsg, NULL, 0, 0)) ! 63: WinDispatchMsg (hab, &qmsg); ! 64: ! 65: WinDestroyWindow (hwndFrame); ! 66: WinDestroyMsgQueue (hmq); ! 67: WinTerminate (hab); ! 68: return 0; ! 69: } ! 70: ! 71: /********************** ClientWndProc **************************/ ! 72: ! 73: MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, ! 74: MPARAM mp1, MPARAM mp2) ! 75: { ! 76: /* Used in switching menus. */ ! 77: static HWND hwndFrame; // Handle to the window frame. ! 78: static HWND hwndMenu; // Handle to the original menu. ! 79: static HWND hwndMenuAlt; // Handle to the switched to menu. ! 80: ! 81: /* Used in the popup menu. */ ! 82: static HWND hwndMenuPopup; // Handle to the popup menu. ! 83: HPS hps; // These 3 variables are used in ! 84: RECTL rcl; // in locating the popup menu. ! 85: POINTL ptlMouse ; ! 86: ! 87: /* Used in enable/disable and checking menu items. */ ! 88: SHORT sState; // Used to toggle 'checked' and ! 89: // 'enabled' menu item state. ! 90: ! 91: /* Used in adding menu items on the fly. */ ! 92: HWND hSubMenu; // Handle to added menu item. ! 93: MENUITEM mi; // Structure to define new menu item. ! 94: static USHORT ActionBarID = 1000; // Used to identify new menu item. ! 95: static USHORT SubMenuID = 6000; // Used to identify new sub menu item. ! 96: CHAR buffer[10]; // Holds text string for menu item. ! 97: MENUCREATETEMPLATE mt; // See type definition in menus.h ! 98: ! 99: ! 100: switch (msg) ! 101: { ! 102: case WM_CREATE: ! 103: /* During the create, the 3 menus are loaded: the original */ ! 104: /* "Cascade Sample Microsoft *Button2 Up Shows Popup Menus"; */ ! 105: /* the popup menu; and the second menu used to switch to */ ! 106: /* "MenuItems". */ ! 107: ! 108: ! 109: /* Loading the popup menu. */ ! 110: hwndMenuPopup = WinLoadMenu (hwnd, 0, ID_POPUP) ; ! 111: WinSetWindowPos (hwndMenuPopup, NULL, ! 112: 0, 0, 0, 0, SWP_SIZE) ; ! 113: WinSetParent (hwndMenuPopup, HWND_DESKTOP, FALSE) ; ! 114: ! 115: /* Setting the original menu's owner to HWND_OBJECT to make it */ ! 116: /* make it disappear. Then loading the second menu, and then */ ! 117: /* setting it's parent to be HWND_OBJECT to make it disappear. */ ! 118: /* And finally setting the original menu's parent to be the */ ! 119: /* window frame again to make it visible. */ ! 120: ! 121: hwndFrame = WinQueryWindow(hwnd, QW_PARENT,FALSE); ! 122: hwndMenu = WinWindowFromID (hwndFrame, FID_MENU); ! 123: WinSetParent(hwndMenu, HWND_OBJECT, TRUE); ! 124: hwndMenuAlt = WinLoadMenu( hwndFrame, 0, ID_ALTERNATE); ! 125: WinSetParent(hwndMenuAlt, HWND_OBJECT, TRUE); ! 126: WinSetParent(hwndMenu, hwndFrame, TRUE); ! 127: return 0; ! 128: ! 129: case WM_COMMAND: ! 130: switch (COMMANDMSG(&msg)->cmd) ! 131: { ! 132: case IDM_ALT_ADD: ! 133: /* From the second menu, when the user chooses to add a new */ ! 134: /* menu item, this is done on the fly. In general you create*/ ! 135: /* a menu, and then insert it. The menu is created with */ ! 136: /* WinCreateMenu using control data in the form of the */ ! 137: /* Resource Type Menu (RT_MENU), or menu creation template. */ ! 138: /* The menu is inserted with a MM_INSERTITEM and a MENUITEM */ ! 139: /* sturcture. */ ! 140: ! 141: /* Filling out the menu template, using many defaults. */ ! 142: mt.size = 0; ! 143: mt.version = 0; ! 144: mt.codepage = 0; ! 145: mt.mnemonic = 0; ! 146: mt.itemcount = 1; ! 147: mt.item[0].afStyle = MIS_TEXT; ! 148: mt.item[0].afAttribute = 0; ! 149: mt.item[0].id = SubMenuID; ! 150: strcpy(mt.item[0].text, ! 151: itoa(SubMenuID++,buffer,10)); ! 152: ! 153: /* Create a popup menu using template information. */ ! 154: hSubMenu = WinCreateMenu( hwndMenuAlt, &mt); ! 155: ! 156: /* Filling out the MENUITEM structure. */ ! 157: mi.iPosition = MIT_END; ! 158: mi.afStyle = MIS_TEXT | MIS_SUBMENU; ! 159: mi.afAttribute = 0; ! 160: mi.id = ActionBarID; ! 161: mi.hwndSubMenu = hSubMenu; ! 162: mi.hItem = 0; ! 163: ! 164: /* Inserting the new item. */ ! 165: WinSendMsg(hwndMenuAlt,MM_INSERTITEM,(MPARAM)&mi, ! 166: (MPARAM)(PCH)itoa(ActionBarID++,buffer,10)); ! 167: break; ! 168: ! 169: ! 170: case IDM_SWITCH: ! 171: /* From the original menu, when the user chooses to switch */ ! 172: /* to the second menu: Set the first menu's parent to be */ ! 173: /* HWND_OBJECT to make it disappear, set the second menu's */ ! 174: /* parent to be the window frame, and then post an update */ ! 175: /* message telling the frame to redraw. */ ! 176: ! 177: WinSetParent(hwndMenu, HWND_OBJECT, TRUE); ! 178: WinSetParent(hwndMenuAlt, hwndFrame, TRUE); ! 179: WinPostMsg (hwndFrame, WM_UPDATEFRAME, ! 180: MPFROMSHORT(FCF_MENU), 0L); ! 181: break; ! 182: ! 183: case IDM_ALT_SWITCH: ! 184: /* From the second menu, when the user chooses to switch */ ! 185: /* back; follow the same procedure as demonstrated for */ ! 186: /* case IDM_SWITCH: */ ! 187: ! 188: WinSetParent(hwndMenuAlt, HWND_OBJECT, TRUE); ! 189: WinSetParent(hwndMenu, hwndFrame, TRUE); ! 190: WinPostMsg (hwndFrame, WM_UPDATEFRAME, ! 191: MPFROMSHORT(FCF_MENU), 0L); ! 192: break; ! 193: ! 194: case IDM_DISABLE: ! 195: /* From the original menu, when the user chooses to disable */ ! 196: /* the cascading menu items, the "Disable Cascade" sub-menu */ ! 197: /* item is checked, and the "Cascade" sub-menu item and its */ ! 198: /* cascaded items are grayed out and disabled. The user can */ ! 199: /* reactivate it by selecting "Disable Cascade" again. To */ ! 200: /* toggle a menu items MIA_* attribute state, query its state*/ ! 201: /* using MM_QUERYITEMATTR. Toggle the value using the found */ ! 202: /* state and XORing it with the chosen MIA_* value, and then */ ! 203: /* reset the attribute value with MM_SETITEMATTR. */ ! 204: ! 205: /* Toggling the check on "Disable Cascade". */ ! 206: (MRESULT)sState = WinSendMsg( hwndMenu, ! 207: MM_QUERYITEMATTR, ! 208: MPFROM2SHORT(IDM_DISABLE, TRUE), ! 209: MPFROMSHORT(MIA_CHECKED)); ! 210: ! 211: sState ^= MIA_CHECKED; ! 212: ! 213: WinSendMsg(hwndMenu, ! 214: MM_SETITEMATTR, ! 215: MPFROM2SHORT(IDM_DISABLE, TRUE), ! 216: MPFROM2SHORT(MIA_CHECKED, sState)); ! 217: ! 218: ! 219: /* Toggling the enable for "Cascade". */ ! 220: (MRESULT)sState = WinSendMsg( hwndMenu, ! 221: MM_QUERYITEMATTR, ! 222: MPFROM2SHORT(IDM_SUB3, TRUE), ! 223: MPFROMSHORT(MIA_DISABLED)); ! 224: ! 225: sState ^= MIA_DISABLED; ! 226: ! 227: WinSendMsg(hwndMenu, ! 228: MM_SETITEMATTR, ! 229: MPFROM2SHORT(IDM_SUB3, TRUE), ! 230: MPFROM2SHORT(MIA_DISABLED, sState)); ! 231: break; ! 232: ! 233: ! 234: default: ! 235: /* A catch all default which explains that the action menu */ ! 236: /* items have no functionality. */ ! 237: ! 238: WinAlarm(HWND_DESKTOP, WA_NOTE); ! 239: WinMessageBox (HWND_DESKTOP, hwnd, ! 240: "This item has no functionality.", ! 241: "PM Menus Code", ! 242: 0, MB_OK | MB_ICONASTERISK ); ! 243: break; ! 244: } ! 245: ! 246: case WM_PAINT: ! 247: /* A simple client space paint. */ ! 248: ! 249: hps = WinBeginPaint (hwnd, NULL, NULL); ! 250: GpiErase (hps); ! 251: WinQueryWindowRect (hwnd, &rcl); ! 252: WinEndPaint (hps); ! 253: return 0; ! 254: ! 255: ! 256: case WM_BUTTON2UP: ! 257: /* When the user activates the popup menu with the Button2Up, */ ! 258: /* First query the position of the mouse, display the popup menu */ ! 259: /* using the WinSetWindowPos, and then capture the mouse to this */ ! 260: /* window. */ ! 261: ! 262: WinQueryPointerPos (HWND_DESKTOP, &ptlMouse) ; ! 263: ! 264: ptlMouse.y += WinQuerySysValue (HWND_DESKTOP, SV_CYMENU) ; ! 265: ! 266: WinSetWindowPos (hwndMenuPopup, HWND_TOP, ! 267: (SHORT) ptlMouse.x, (SHORT) ptlMouse.y, ! 268: 0, 0, SWP_MOVE | SWP_SHOW) ; ! 269: ! 270: WinSendMsg (hwndMenuPopup, MM_SELECTITEM, ! 271: MPFROM2SHORT (IDM_POPUP, FALSE), ! 272: MPFROMSHORT (FALSE)) ; ! 273: ! 274: WinSetCapture (HWND_DESKTOP, hwndMenuPopup) ; ! 275: return 0 ; ! 276: ! 277: ! 278: ! 279: ! 280: case WM_HELP: ! 281: WinMessageBox (HWND_DESKTOP, hwnd, "Help Message Box", ! 282: "PM Menus Code", 0, ! 283: MB_OK | MB_ICONASTERISK); ! 284: break; ! 285: ! 286: case WM_DESTROY: ! 287: return 0; ! 288: } ! 289: return WinDefWindowProc (hwnd, msg, mp1, mp2); ! 290: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.