Now let's step a little off the beaten path. Instead of having drop-down menus in your program, how about creating multiple top-level menus without any popups and switching between the top-level menus using the SetMenu call? The NOPOPUPS program, shown in Figure 9-7, demonstrates how to do it. This program includes similar File and Edit items that MENUDEMO uses but displays them as alternate top-level menus.
NOPOPUPS.MAK
#------------------------
# NOPOPUPS.MAK make file
#------------------------
nopopups.exe : nopopups.obj nopopups.def nopopups.res
link nopopups, /align:16, NUL, /nod slibcew libw, nopopups
rc nopopups.res
nopopups.obj : nopopups.c nopopups.h
cl -c -Gsw -Ow -W2 -Zp nopopups.c
nopopups.res : nopopups.rc nopopups.h
rc -r nopopups.rc
NOPOPUPS.C
/*-------------------------------------------------
NOPOPUPS.C -- Demonstrates No-Popup Nested Menu
(c) Charles Petzold, 1990
-------------------------------------------------*/
#include <windows.h>
#include "nopopups.h"
long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szAppName [] = "NoPopUps" ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass) ;
}
hwnd = CreateWindow (szAppName, "No-Popup Nested Menu Demonstration",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, nCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ; DispatchMessage (&msg) ;
}
return msg.wParam ;
}
long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
static HMENU hMenuMain, hMenuEdit, hMenuFile ;
HANDLE hInstance ;
switch (message)
{
case WM_CREATE :
hInstance = GetWindowWord (hwnd, GWW_HINSTANCE) ;
hMenuMain = LoadMenu (hInstance, "MenuMain") ;
hMenuFile = LoadMenu (hInstance, "MenuFile") ;
hMenuEdit = LoadMenu (hInstance, "MenuEdit") ;
SetMenu (hwnd, hMenuMain) ;
return 0 ;
case WM_COMMAND :
switch (wParam)
{
case IDM_MAIN :
SetMenu (hwnd, hMenuMain) ;
return 0 ;
case IDM_FILE :
SetMenu (hwnd, hMenuFile) ;
return 0 ;
case IDM_EDIT :
SetMenu (hwnd, hMenuEdit) ;
return 0 ;
case IDM_NEW :
case IDM_OPEN :
case IDM_SAVE :
case IDM_SAVEAS :
case IDM_UNDO :
case IDM_CUT :
case IDM_COPY :
case IDM_PASTE :
case IDM_CLEAR :
MessageBeep (0) ;
return 0 ;
}
break ; case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
NOPOPUPS.RC
/*-----------------------------
NOPOPUPS.RC resource script
-----------------------------*/
#include "nopopups.h"
MenuMain MENU
{
MENUITEM "MAIN:", 0, INACTIVE
MENUITEM "&File...", IDM_FILE
MENUITEM "&Edit...", IDM_EDIT
}
MenuFile MENU
{
MENUITEM "FILE:", 0, INACTIVE
MENUITEM "&New", IDM_NEW
MENUITEM "&Open...", IDM_OPEN
MENUITEM "&Save", IDM_SAVE
MENUITEM "Save &As...", IDM_SAVEAS
MENUITEM "(&Main)", IDM_MAIN
}
MenuEdit MENU
{
MENUITEM "EDIT:", 0, INACTIVE
MENUITEM "&Undo", IDM_UNDO
MENUITEM "Cu&t", IDM_CUT
MENUITEM "&Copy", IDM_COPY
MENUITEM "&Paste", IDM_PASTE
MENUITEM "C&lear", IDM_CLEAR
MENUITEM "(&Main)", IDM_MAIN
}
NOPOPUPS.H
/*------------------------
NOPOPUPS.H header file
------------------------*/
#define IDM_NEW 1
#define IDM_OPEN 2
#define IDM_SAVE 3
#define IDM_SAVEAS 4
#define IDM_UNDO 5
#define IDM_CUT 6
#define IDM_COPY 7
#define IDM_PASTE 8
#define IDM_CLEAR 9
#define IDM_MAIN 10
#define IDM_EDIT 11
#define IDM_FILE 12
NOPOPUPS.DEF
;-------------------------------------
; NOPOPUPS.DEF module definition file
;-------------------------------------
NAME NOPOPUPS
DESCRIPTION 'Demonstration of No-Popup Menu (c) Charles Petzold, 1990'
EXETYPE WINDOWS
STUB 'WINSTUB.EXE'
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE MULTIPLE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS WndProc
The resource script has three menus rather than one. When the window procedure processes the WM_CREATE message, Windows loads each of the menu resources into memory:
hMenuMain = LoadMenu (hInstance, "MenuMain") ;
hMenuFile = LoadMenu (hInstance, "MenuFile") ;
hMenuEdit = LoadMenu (hInstance, "MenuEdit") ;
Initially, the program displays the main menu:
SetMenu (hwnd, hMenuMain) ;
The main menu lists the three options using the character strings ”MAIN:“, ”File...^^, and ”Edit...^^ However, ”MAIN:“ is disabled, so it doesn't cause WM_COMMAND messages to be sent to the window procedure. The File and Edit menus begin ”FILE:“ and ”EDIT:“ to identify these as submenus. The last item in each menu is the character string ”(Main)“; this option indicates a return to the main menu. Switching among these three menus is simple:
case WM_COMMAND :
switch (wParam)
{
case IDM_MAIN :
SetMenu (hwnd, hMenuMain) ;
return 0 ;
case IDM_FILE :
SetMenu (hwnd, hMenuFile) ;
return 0 ;
case IDM_EDIT :
SetMenu (hwnd, hMenuEdit) ;
return 0 ;
[other program lines]
}
break ;