home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * *
- * PROGRAM : Menu.c *
- * *
- * PURPOSE : To give a demonstration of the use of popup menus, user *
- * defined menus and menu functions. *
- * *
- * FUNCTIONS : WinMain() - Calls the initialization function *
- * and enters the message loop. *
- * *
- * MenuInit() - Registers the app. window class. *
- * *
- * About() - Dialog function for the About.. *
- * dialog. *
- * *
- * ShrinkBitmap() - Shrinks a 64x64 bitmap to a size *
- * useable for a user-defined menu *
- * checkmark. *
- * *
- * HandleCreate() - Creates a new menu and appends it *
- * to the main menu *
- * *
- * HandlePaint() - Handles repainting the app's client*
- * area *
- * *
- * HandleChangeColors()- Changes the state of the "colors" *
- * menu item. *
- * *
- * HandleDrawItem() - Redraws the menu items in the *
- * "colors" menu *
- * *
- * HandlePopupMenu() - handles display of the "floating" *
- * popup. *
- * *
- * MenuWndProc() - Window function for the app. *
- * *
- * *
- ***************************************************************************/
- #include "windows.h"
- #include "menu.h"
-
- HANDLE hInst;
- HMENU hBigMenu;
- HBITMAP hbmCheckOn;
- HBITMAP hbmCheckOff;
-
- /****************************************************************************
- * *
- * FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
- * *
- * PURPOSE : Creates the main app. window, calls an initialization *
- * function and enters the message loop. *
- * *
- ****************************************************************************/
- int PASCAL WinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow)
-
- HANDLE hInstance, hPrevInstance;
- LPSTR lpCmdLine;
- int nCmdShow;
-
- {
- HWND hWnd;
- MSG msg;
-
- /* Register main window class if this is the first instance of the app. */
- if (!hPrevInstance)
- if (!MenuInit (hInstance))
- return NULL;
-
- hInst = hInstance;
-
- /* Create the app. window */
- hWnd = CreateWindow ("menu",
- "Menu Example",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- (HWND) NULL,
- NULL,
- hInstance,
- (LPSTR) NULL);
-
- if (!hWnd)
- return NULL;
-
- ShowWindow (hWnd, nCmdShow);
- UpdateWindow (hWnd);
-
- while (GetMessage (&msg, NULL, NULL, NULL)){
- /* Since we have no accelerators, no need to call
- * TranslateAccelerator here.
- */
- TranslateMessage (&msg);
- DispatchMessage (&msg);
- }
- return(msg.wParam);
- }
-
-
- /****************************************************************************
- * *
- * FUNCTION : MenuInit (hInstance) *
- * *
- * PURPOSE : Registers the main window class. *
- * *
- * RETURNS : TRUE - if RegisterClass() went off ok *
- * FALSE - otherwise. *
- * *
- ****************************************************************************/
- BOOL NEAR PASCAL MenuInit (hInstance)
-
- HANDLE hInstance;
-
- {
- HANDLE hMemory;
- PWNDCLASS pWndClass;
- BOOL bSuccess;
-
- /* Initialize the menu window class */
- hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
- pWndClass = (PWNDCLASS) LocalLock(hMemory);
-
- pWndClass->style = NULL;
- pWndClass->lpfnWndProc = MenuWndProc;
- pWndClass->hInstance = hInstance;
- pWndClass->hIcon = LoadIcon (hInstance, "menu");
- pWndClass->hCursor = LoadCursor (NULL, IDC_ARROW);
- pWndClass->hbrBackground = GetStockObject (WHITE_BRUSH);
- pWndClass->lpszMenuName = (LPSTR) "MenuMenu",
- pWndClass->lpszClassName = (LPSTR) "menu";
-
- bSuccess = RegisterClass (pWndClass);
- LocalUnlock (hMemory);
- LocalFree (hMemory);
-
- return bSuccess;
- }
-
-
- /****************************************************************************
- * *
- * FUNCTION : About (hDlg, message, wParam, lParam) *
- * *
- * PURPOSE : Dialog function for the About menu... dialog. *
- * *
- ****************************************************************************/
- BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
-
- HWND hDlg;
- unsigned message;
- WORD wParam;
- LONG lParam;
-
- {
- switch (message){
- case WM_INITDIALOG:
- return(TRUE);
-
- case WM_COMMAND:
- if (wParam == IDOK){
- EndDialog(hDlg,NULL);
- return(TRUE);
- }
- break;
- }
- return(FALSE);
- }
-
-
- /****************************************************************************
- * *
- * FUNCTION : ShrinkBitmap(hwnd, hbm) *
- * *
- * PURPOSE : This function shrinks a 64x64 bitmap into a bitmap useable *
- * for the user-defined checkmark for menu items. This can be *
- * easily generalized to shrink bitmaps of any size. *
- * *
- * RETURNS : HBITMAP - A handle to the new bitmap. *
- * *
- ****************************************************************************/
- HBITMAP FAR PASCAL ShrinkBitmap (hwnd, hbm)
-
- HWND hwnd;
- HBITMAP hbm;
-
- {
- HDC hdc;
- HDC hmemorydcNew;
- HDC hmemorydcOld;
- LONG checkMarkSize;
- HBITMAP hCheckBitmap;
- HBITMAP hOldBitmapSave;
- HBITMAP hNewBitmapSave;
-
- hdc = GetDC (hwnd);
-
- /* Create DCs for the source (old) and target (new) bitmaps */
- hmemorydcNew = CreateCompatibleDC (hdc);
- hmemorydcOld = CreateCompatibleDC (hdc);
-
- /* Determine the dimensions of the default menu checkmark and
- * create a target bitmap of the same dimensions
- */
- checkMarkSize = GetMenuCheckMarkDimensions ();
- hCheckBitmap = CreateCompatibleBitmap (hdc,
- LOWORD (checkMarkSize),
- HIWORD (checkMarkSize));
-
- /* Select the source bitmap and the target bitmap into their
- * respective DCs.
- */
- hOldBitmapSave = SelectObject (hmemorydcNew, hCheckBitmap);
- hNewBitmapSave = SelectObject (hmemorydcOld, hbm);
-
- /* Shrink the source bitmap into the target DC */
- StretchBlt (hmemorydcNew,
- 0,
- 0,
- LOWORD(checkMarkSize),
- HIWORD(checkMarkSize),
- hmemorydcOld,
- 0,
- 0,
- 64,
- 64,
- SRCCOPY);
-
- /* De-select the bitmaps and clean up .. */
- SelectObject (hmemorydcNew, hOldBitmapSave);
- SelectObject (hmemorydcOld, hNewBitmapSave);
- DeleteDC (hmemorydcNew);
- DeleteDC (hmemorydcOld);
- ReleaseDC (hwnd, hdc);
-
- /* .. and return a handle to the target bitmap */
- return hCheckBitmap;
- }
-
-
- /****************************************************************************
- * *
- * FUNCTION : HandleCreate ( hwnd ) *
- * *
- * PURPOSE : Creates a new (empty) menu and appends to it the "State" *
- * menu items. It sets up the user-defined checkmarks for the *
- * menu. It then inserts this menu into the main menu bar. *
- * *
- ****************************************************************************/
- void FAR PASCAL HandleCreate (hwnd)
- HWND hwnd;
- {
- HMENU hMenu;
- HMENU hWndMenu;
- HBITMAP hbmOn;
- HBITMAP hbmOff;
-
- /* Create a new menu into the menubar on the fly */
- hMenu = CreateMenu ();
- if (!hMenu)
- return;
-
- /* Append the state menu items to it */
- AppendMenu (hMenu, MF_STRING, IDM_STATE1, "South Dakota");
- AppendMenu (hMenu, MF_STRING, IDM_STATE2, "Washington");
- AppendMenu (hMenu, MF_STRING, IDM_STATE3, "California");
- if (!AppendMenu (hMenu, MF_STRING, IDM_STATE4, "Oregon")){
- /* It is unlikely the other appends will fail and this will succeed.
- * So just check this one. And if it fails, Destroy the menu for
- * good measure and return.
- */
- DestroyMenu(hMenu);
- return;
- }
- hbmCheckOn = ShrinkBitmap (hwnd, LoadBitmap (hInst, "checkon"));
- hbmCheckOff = ShrinkBitmap (hwnd, LoadBitmap (hInst, "checkoff"));
-
- /* Set up the user-defined check marks */
- SetMenuItemBitmaps (hMenu, 0, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
- SetMenuItemBitmaps (hMenu, 1, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
- SetMenuItemBitmaps (hMenu, 2, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
- SetMenuItemBitmaps (hMenu, 3, MF_BYPOSITION, hbmCheckOff, hbmCheckOn);
-
- /* Now insert the menu into the main menu bar. */
- hWndMenu = GetMenu (hwnd);
- InsertMenu (hWndMenu, 2, MF_POPUP|MF_BYPOSITION, (WORD)hMenu, "States");
-
- return;
- }
-
- /****************************************************************************
- * *
- * FUNCTION : HandlePaint ( hwnd ) *
- * *
- * PURPOSE : Handles the repainting of the main app's client area. *
- * *
- ****************************************************************************/
- void FAR PASCAL HandlePaint (hwnd)
- HWND hwnd;
- {
- HDC hdc;
- PAINTSTRUCT ps;
- RECT rc;
-
- hdc = BeginPaint (hwnd, (LPPAINTSTRUCT)&ps);
-
- /* Center the text in the client area */
- GetClientRect (hwnd, (LPRECT)&rc);
- DrawText (hdc,
- "Down click in the window for a popup menu",
- 41,
- (LPRECT)&rc,
- DT_CENTER | DT_WORDBREAK);
- EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
- }
-
-
- /****************************************************************************
- * *
- * FUNCTION : HandleChangeColors (hwnd) *
- * *
- * PURPOSE : Toggles the state of the Owner Draw item in the Colors *
- * menu. If it is on, the "Black", "Blue", "Red", and "Green" *
- * individual menu text items are modified so that they will *
- * contain bands of color. Otherwise, the colors are replaced *
- * by the text. *
- * *
- ****************************************************************************/
- void FAR PASCAL HandleChangeColors(hwnd)
- HWND hwnd;
- {
- HMENU hMenu;
- BOOL fOwnerDraw;
-
- /* Get a handle to the Colors menu. This is at position 1. */
- hMenu = GetSubMenu (GetMenu (hwnd), IDCOLORS_POS);
-
- /* Get the current state of the item */
- fOwnerDraw = GetMenuState ( hMenu,
- IDM_COLOROWNERDR, MF_BYCOMMAND) & MF_CHECKED;
-
- /* Toggle the state of the item. */
- CheckMenuItem ( hMenu,
- IDM_COLOROWNERDR,
- MF_BYCOMMAND | (fOwnerDraw ? MF_UNCHECKED : MF_CHECKED));
-
- if (!fOwnerDraw){
- /* Change the items to owner-draw items. Pass the RGB value for the
- * color as the application-supplied data. This makes it easier for
- * us to draw the items.
- */
- ModifyMenu(hMenu,
- IDM_BLACK,
- MF_OWNERDRAW | MF_BYCOMMAND,
- IDM_BLACK,
- (LPSTR)RGB (0,0,0));
-
- ModifyMenu(hMenu,
- IDM_BLUE,
- MF_OWNERDRAW | MF_BYCOMMAND,
- IDM_BLUE,
- (LPSTR)RGB (0,0,255));
-
- ModifyMenu(hMenu,
- IDM_RED,
- MF_OWNERDRAW | MF_BYCOMMAND,
- IDM_RED,
- (LPSTR)RGB (255,0,0));
-
- ModifyMenu(hMenu,
- IDM_GREEN,
- MF_OWNERDRAW | MF_BYCOMMAND,
- IDM_GREEN,
- (LPSTR)RGB (0,255,0));
- }
- else {
- /* Change the items to normal text items. */
- ModifyMenu(hMenu, IDM_BLACK, MF_BYCOMMAND, IDM_BLACK, "Black");
-
- ModifyMenu(hMenu, IDM_BLUE, MF_BYCOMMAND, IDM_BLUE, "Blue");
-
- ModifyMenu(hMenu, IDM_RED, MF_BYCOMMAND, IDM_RED, "Red");
-
- ModifyMenu(hMenu, IDM_GREEN, MF_BYCOMMAND, IDM_GREEN, "Green");
- }
- }
-
-
- /****************************************************************************
- * *
- * FUNCTION : HandleDrawItem ( hwnd, lpdis) *
- * *
- * PURPOSE : Called in response to a WM_DRAWITEM message, i.e. when the *
- * colors menu is being modified to an owner-draw menu, or *
- * one of the items is selected. It sizes the checkmark bitmap*
- * to fit next to a color band and draws the color bands and *
- * the checkmark on the popup menu. *
- * *
- ****************************************************************************/
- void FAR PASCAL HandleDrawItem(hwnd, lpdis)
- HWND hwnd;
- LPDRAWITEMSTRUCT lpdis;
-
- {
- HDC hdcBitmap;
- HBITMAP hbmSave;
- HBRUSH hbr;
- RECT rc;
- LONG checkMarkSize;
- DWORD textColorSave;
- DWORD bkColorSave;
-
- /* Get the size of the checkmark so we can leave room for it since we
- * want to be able to check the selected color.
- */
- checkMarkSize = GetMenuCheckMarkDimensions ();
-
- if (lpdis->itemAction == ODA_SELECT ||
- lpdis->itemAction == ODA_DRAWENTIRE){
-
- CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
- InflateRect ((LPRECT)&rc, (-2 - LOWORD(checkMarkSize)), -2);
-
- if (lpdis->itemState & ODS_SELECTED)
- {
- /* Item has been selected -- hilite with a gray frame */
- hbr = GetStockObject (GRAY_BRUSH);
- FrameRect (lpdis->hDC, (LPRECT)&rc, hbr);
- }
- else if (lpdis->itemAction == ODA_SELECT)
- {
- /* Item has been de-selected -- remove gray frame */
- hbr = CreateSolidBrush (GetSysColor (COLOR_MENU));
- FrameRect (lpdis->hDC, (LPRECT)&rc, hbr);
- DeleteObject (hbr);
- }
- }
-
- if (lpdis->itemAction == ODA_DRAWENTIRE){
-
- /* Paint the color item in the color requested. */
- hbr = CreateSolidBrush (lpdis->itemData);
- CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem);
- InflateRect ((LPRECT)&rc, -10-LOWORD(checkMarkSize), -10);
- FillRect (lpdis->hDC, (LPRECT)&rc, hbr);
- DeleteObject (hbr);
-
- if (lpdis->itemState & ODS_CHECKED){
- /* Draw the check mark if the item is checked. */
- hdcBitmap = CreateCompatibleDC (lpdis->hDC);
- hbmSave = SelectObject (hdcBitmap, hbmCheckOn);
-
- textColorSave = SetTextColor (lpdis->hDC, 0x00000000L);
- bkColorSave = SetBkColor (lpdis->hDC, 0x00FFFFFFL);
-
- /* Use Magic bitblt op so that monochrome bitmaps preserve
- background and foreground colors. */
- BitBlt (lpdis->hDC,
- lpdis->rcItem.left,
- lpdis->rcItem.top+
- (MEASUREITEMHEIGHT - HIWORD (checkMarkSize)) / 2,
- LOWORD (checkMarkSize),
- HIWORD (checkMarkSize),
- hdcBitmap,
- 0,
- 0,
- ROP_PSDPxax);
-
- /* Restore colors and bitmap and clean up */
- SetTextColor (lpdis->hDC, textColorSave);
- SetBkColor (lpdis->hDC, bkColorSave);
- SelectObject (hdcBitmap, hbmSave);
- DeleteDC (hdcBitmap);
-
- }
- }
- }
-
- /****************************************************************************
- * *
- * FUNCTION : HandlePopupMenu (hwnd, point) *
- * *
- * PURPOSE : Handles the display of the "floating" popup that appears * *
- * on a mouse click in the app's client area. *
- * *
- ****************************************************************************/
- void FAR PASCAL HandlePopupMenu (hwnd, point)
- HWND hwnd;
- POINT point;
-
- {
- HMENU hMenu;
- HMENU hMenuTrackPopup;
-
- /* Get the menu for the popup from the resource file. */
- hMenu = LoadMenu (hInst, "PopupMenu");
- if (!hMenu)
- return;
-
- /* Get the first menu in it which we will use for the call to
- * TrackPopup(). This could also have been created on the fly using
- * CreatePopupMenu and then we could have used InsertMenu() or
- * AppendMenu.
- */
- hMenuTrackPopup = GetSubMenu (hMenu, 0);
-
- /* Convert the mouse point to screen coordinates since that is what
- * TrackPopup expects.
- */
- ClientToScreen (hwnd, (LPPOINT)&point);
-
- /* Draw and track the "floating" popup */
- TrackPopupMenu (hMenuTrackPopup, 0, point.x, point.y, 0, hwnd, NULL);
-
- /* Destroy the menu since were are done with it. */
- DestroyMenu (hMenu);
- }
-
- /****************************************************************************
- * *
- * FUNCTION : MenuWndProc (hWnd, message, wParam, lParam) *
- * *
- * PURPOSE : Window function for the main app. window. Processes all the*
- * menu selections and oter messages. *
- * *
- ****************************************************************************/
- long FAR PASCAL MenuWndProc (hWnd, message, wParam, lParam)
- HWND hWnd;
- unsigned message;
- WORD wParam;
- LONG lParam;
-
- {
- FARPROC lpProc;
- HMENU hMenu;
- LPDRAWITEMSTRUCT dis;
- RECT rc;
-
-
- switch (message){
- case WM_SYSCOMMAND:
- /* Show the About ... dialog */
- if (wParam == ID_ABOUT){
- lpProc = MakeProcInstance (About, hInst);
- DialogBox (hInst,
- "AboutBox",
- hWnd,
- lpProc);
-
- FreeProcInstance (lpProc);
- break;
- }
- else
- return DefWindowProc (hWnd, message, wParam, lParam);
-
- case WM_COMMAND:
- switch (wParam){
- case IDM_EXIT:
- DestroyWindow (hWnd);
- break;
-
- case IDM_ABOUT:
- /* Bring up the About.. dialog box */
- lpProc = MakeProcInstance (About, hInst);
- DialogBox (hInst,
- "AboutBox",
- hWnd,
- lpProc);
-
- FreeProcInstance (lpProc);
- break;
-
- case IDM_COLOROWNERDR:
- /* Change colors in color menu depending on state of this
- menu item. */
- HandleChangeColors (hWnd);
- break;
-
- case IDM_STATE1:
- case IDM_STATE2:
- case IDM_STATE3:
- case IDM_STATE4:
- /* Get a handle to the states menu... */
- hMenu = GetSubMenu (GetMenu (hWnd), IDSTATES_POS);
-
- /* Uncheck all the items. */
- CheckMenuItem (hMenu, IDM_STATE1,
- MF_BYCOMMAND | MF_UNCHECKED);
- CheckMenuItem (hMenu, IDM_STATE2,
- MF_BYCOMMAND | MF_UNCHECKED);
- CheckMenuItem (hMenu, IDM_STATE3,
- MF_BYCOMMAND | MF_UNCHECKED);
- CheckMenuItem (hMenu, IDM_STATE4,
- MF_BYCOMMAND | MF_UNCHECKED);
-
- /* ...and just check the selected one.*/
- CheckMenuItem (hMenu, wParam,
- MF_BYCOMMAND | MF_CHECKED);
- break;
-
- case IDM_BLACK:
- case IDM_RED:
- case IDM_BLUE:
- case IDM_GREEN:
- /* Get a handle to the Colors menu. */
- hMenu = GetSubMenu (GetMenu (hWnd),IDCOLORS_POS);
-
- /* Uncheck all the items. */
- CheckMenuItem (hMenu, IDM_BLACK,
- MF_BYCOMMAND | MF_UNCHECKED);
- CheckMenuItem (hMenu, IDM_RED,
- MF_BYCOMMAND | MF_UNCHECKED);
- CheckMenuItem (hMenu, IDM_BLUE,
- MF_BYCOMMAND | MF_UNCHECKED);
- CheckMenuItem (hMenu, IDM_GREEN,
- MF_BYCOMMAND | MF_UNCHECKED);
-
- /* ...and just check the selected one.*/
- CheckMenuItem (hMenu, wParam,
- MF_BYCOMMAND | MF_CHECKED);
- break;
-
- case IDM_FONT:
- /* Messages sent to us from TrackPopupMenu when
- * items are selected from the "floating" popups
- */
- MessageBox (hWnd,
- "A font was selected",
- "Popup Menu Alert",
- MB_APPLMODAL|MB_OK);
- break;
-
- case IDM_SIZE:
- MessageBox (hWnd,
- "A size was selected",
- "Popup Menu Alert",
- MB_APPLMODAL|MB_OK);
- break;
-
- case IDM_STYLE:
- MessageBox (hWnd,
- "A style was selected",
- "Popup Menu Alert",
- MB_APPLMODAL|MB_OK);
- break;
- }
- break;
-
- case WM_SIZE:
- if (lParam){
- /* If window is being sized to a non zero value...
- * invalidate it's client area.
- */
- InvalidateRect (hWnd, NULL, TRUE);
- }
- break;
-
- case WM_PAINT:
- HandlePaint (hWnd);
- break;
-
- case WM_MEASUREITEM:
- /* Use the same width for all items. We could examine the item id
- and use different widths/heights for each item. */
- ((LPMEASUREITEMSTRUCT)lParam)->itemWidth = MEASUREITEMWIDTH;
- ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = MEASUREITEMHEIGHT;
- return TRUE;
-
- case WM_DRAWITEM:
- /* Redraw the "colors" menu in normal/ownerdrawmode */
- HandleDrawItem (hWnd,(LPDRAWITEMSTRUCT)lParam);
- return TRUE;
- break;
-
- case WM_CREATE:
- /* Create the menu */
- HandleCreate (hWnd);
- break;
-
- case WM_DESTROY:
- /* Delete the on/off bitmaps so that they don't waste memory. */
- DeleteObject (hbmCheckOn);
- DeleteObject (hbmCheckOff);
-
- PostQuitMessage (0);
- break;
-
- case WM_LBUTTONDOWN:
- /* Draw the "floating" popup in the app's client area */
- GetClientRect (hWnd, (LPRECT)&rc);
- if (PtInRect ((LPRECT)&rc, MAKEPOINT (lParam)))
- HandlePopupMenu (hWnd, lParam);
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return(NULL);
- }
-