二、Windows菜单—建立菜单的非正统方法
现在让我们稍微偏离我们所讨论的主题。如果在您的程序中没有下拉式菜单,而是建立了多个没有弹出式菜单的顶层菜单,并呼叫SetMenu在顶层菜单之间切换,那会是什么样的情形呢?就像Lotus 1-2-3中老式的文字模式菜单那样。程序10-8中的NOPOPUPS程序展示了处理这种情况。在这个程序中,「File」和「Edit」项与MENUDEMO程序中的类似,但是却以另一种顶层菜单显示出来。
        
NOPOPUPS.C
        
/*-------------------------------------------------------------------------
        
  NOPOPUPS.C --         Demonstrates No-Popup Nested Menu
        
                                                         (c) Charles Petzold, 1998
        
-------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include "resource.h"
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                         PSTR szCmdLine, int iCmdShow)
        
{
        
           static TCHAR szAppName[] = TEXT ("NoPopUps") ;
        
           HWND                                 hwnd ;
        
           MSG                                  msg ;
        
           WNDCLASS                      wndclass ;
        
   
        
           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              = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
           wndclass.lpszMenuName                = NULL ;
        
           wndclass.lpszClassName = szAppName ;
        
           if (!RegisterClass (&wndclass))
        
           {
        
           MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                                         szAppName, MB_ICONERROR) ;
        
           return 0 ;
        
    }
        
   
        
           hwnd = CreateWindow (szAppName,
        
                TEXT ("No-Popup Nested Menu Demonstration"),
        
                WS_OVERLAPPEDWINDOW,
        
                CW_USEDEFAULT, CW_USEDEFAULT,
        
                CW_USEDEFAULT, CW_USEDEFAULT,
        
                NULL, NULL, hInstance, NULL) ;
        
   
        
           ShowWindow (hwnd, iCmdShow) ;
        
           UpdateWindow (hwnd) ;
        
   
        
           while (GetMessage (&msg, NULL, 0, 0))
        
           {
        
                  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }
        
           return msg.wParam ;
        
}
        
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
           static HMENU hMenuMain, hMenuEdit, hMenuFile ;
        
           HINSTANCE             hInstance ;
        
           switch (message)
        
    {
        
           case   WM_CREATE:
        
                  hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;
        
        
        
                  hMenuMain = LoadMenu (hInstance, TEXT ("MenuMain")) ;
        
                  hMenuFile = LoadMenu (hInstance, TEXT ("MenuFile")) ;
        
                  hMenuEdit = LoadMenu (hInstance, TEXT ("MenuEdit")) ;
        
      
        
                  SetMenu (hwnd, hMenuMain) ;
        
                  return 0 ;
        
        
        
           case   WM_COMMAND:
        
                  switch (LOWORD (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_FILE_NEW:
        
                  case   IDM_FILE_OPEN:
        
                  case   IDM_FILE_SAVE:
        
                  case   IDM_FILE_SAVE_AS:
        
                  case   IDM_EDIT_UNDO:
        
                  case   IDM_EDIT_CUT:
        
                  case   IDM_EDIT_COPY:
        
                  case   IDM_EDIT_PASTE:
        
                  case   IDM_EDIT_CLEAR:
        
                                         MessageBeep (0) ;
        
                                         return 0 ;
        
                  }
        
                  break ;
        
        
        
           case   WM_DESTROY:
        
                  SetMenu (hwnd, hMenuMain) ;
        
                 DestroyMenu (hMenuFile) ;
        
                  DestroyMenu (hMenuEdit) ;
        
                  PostQuitMessage (0) ;
        
                  return 0 ;
        
    }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
NOPOPUPS.RC (摘录)
        
//Microsoft Developer Studio generated resource script.
        
#include "resource.h"
        
#include "afxres.h"
        
/////////////////////////////////////////////////////////////////////////////
        
// Menu
        
MENUMAIN MENU DISCARDABLE
        
BEGIN
        
   MENUITEM "MAIN:",         0, INACTIVE
        
   MENUITEM "&File...",  IDM_FILE
        
   MENUITEM "&Edit...", IDM_EDIT
        
END
        
MENUFILE MENU DISCARDABLE                                               
        
BEGIN
        
   MENUITEM "FILE:",             0, INACTIVE
        
   MENUITEM "&New",                                                               IDM_FILE_NEW
        
   MENUITEM "&Open...",                                             IDM_FILE_OPEN
        
   MENUITEM "&Save",                                                     IDM_FILE_SAVE
        
   MENUITEM "Save &As",                                              IDM_FILE_SAVE_AS
        
   MENUITEM "(&Main)",                                                           IDM_MAIN
        
END
        
MENUEDIT MENU DISCARDABLE                                               
        
BEGIN
        
   MENUITEM "EDIT:",                             0, INACTIVE
        
   MENUITEM "&Undo",                                                        IDM_EDIT_UNDO
        
   MENUITEM "Cu&t",                     IDM_EDIT_CUT
        
   MENUITEM "&Copy",                     IDM_EDIT_COPY
        
   MENUITEM "&Paste",                    IDM_EDIT_PASTE
        
   MENUITEM "De&lete",                  IDM_EDIT_CLEAR
        
   MENUITEM "(&Main)",                   IDM_MAIN
        
END
        
RESOURCE.H (摘录)
        
// Microsoft Developer Studio generated include file.
        
// Used by NoPopups.rc
        
#define IDM_FILE                   40001
        
#define IDM_EDIT                   40002
        
#define IDM_FILE_NEW               40003
        
#define IDM_FILE_OPEN              40004
        
#define IDM_FILE_SAVE              40005
        
#define IDM_FILE_SAVE_AS          40006
        
#define IDM_MAIN                  40007
        
#define IDM_EDIT_UNDO              40008
        
#define IDM_EDIT_CUT               40009
        
#define IDM_EDIT_COPY              40010
        
#define IDM_EDIT_PASTE             40011
        
#define IDM_EDIT_CLEAR             40012
        
在Microsoft Developer Studio中,您建立了三个菜单,而不是一个。从「Insert」中选择「Resource」三次,每个菜单有一个不同的名称。当窗口消息处理程序处理WM_CREATE消息时,Windows将每个菜单资源加载内存:
hMenuMain = LoadMenu (hInstance, TEXT ("MenuMain")) ;
        
hMenuFile = LoadMenu (hInstance, TEXT ("MenuFile")) ;
        
hMenuEdit = LoadMenu (hInstance, TEXT ("MenuEdit")) ;
        
开始时,程序只显示主菜单:
SetMenu (hwnd, hMenuMain) ;
        
主菜单使用字符串「MAIN:」、「File...」和「Edit...」列出这三个选项。然而,「MAIN:」是禁用的,因此它不能使WM_COMMAND消息被发送到窗口消息处理程序。「File」和「Edit」菜单项以「FILE:」和「EDIT:」开始,表示它们是子菜单。每个菜单的最后一项都是字符串「(Main)」,表示传回到主菜单。在这三个菜单之间进行切换是很简单的:
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 ;
        
   其它行程序
        
   }
        
          break ;
        
在WM_DESTROY消息处理期间,NOPOPUPS将程序的菜单设定为主菜单,并呼叫DestroyMenu来清除「File」和「Edit」菜单。当窗口被清除时,主菜单将被自动清除。
