二、Windows菜单—使用系统菜单
使用WS_SYSMENU样式建立的父窗口,在其标题列的左侧有一个系统菜单按钮。如果您愿意,可以修改这个菜单。在Windows程序设计的早期,程序写作者一般把「About」菜单项放入系统菜单。虽然这种方法不常见,但是修改系统菜单往往是一种在短程序中添加菜单的快速偷懒方法。这里唯一的限制是:在系统菜单中增加的命令其ID值必须小于0xF000;否则它们将会与Windows系统菜单命令所使用的ID值相冲突。还要记住,当您为这些新菜单项在窗口消息处理程序中处理WM_SYSCOMMAND消息时,您必须把其它的WM_SYSCOMMAND消息发送给DefWindowProc。如果您不这样做,那么实际上是禁用了系统菜单上的所有正常选项。
程序10-7中所示的POORMENU(「设计不当的个人菜单」)在系统菜单中加入了一个分隔条和三个命令,最后一个命令将删除这些附加的菜单项。
程序10-7  POORMENU
        
POORMENU.C
        
/*-------------------------------------------------------------------------
        
  POORMENU.C --         The Poor Person's Menu
        
                                                         (c) Charles Petzold, 1998
        
--------------------------------------------------------------------------*/
        
#include <windows.h>
        
#define IDM_SYS_ABOUT                             1
        
#define IDM_SYS_HELP                              2
        
#define IDM_SYS_REMOVE                       3
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
static TCHAR szAppName[] = TEXT ("PoorMenu") ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                         PSTR szCmdLine, int iCmdShow)
        
{
        
           HMENU                                hMenu ;
        
          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 ("The Poor-Person's Menu"),
        
                        WS_OVERLAPPEDWINDOW,
        
                        CW_USEDEFAULT, CW_USEDEFAULT,
        
                        CW_USEDEFAULT, CW_USEDEFAULT,
        
                        NULL, NULL, hInstance, NULL) ;
        
   
        
           hMenu = GetSystemMenu (hwnd, FALSE) ;
        
           AppendMenu    (hMenu, MF_SEPARATOR, 0,                                 NULL) ;
        
           AppendMenu    (hMenu, MF_STRING, IDM_SYS_ABOUT,    TEXT ("About...")) ;
        
           AppendMenu    (hMenu, MF_STRING, IDM_SYS_HELP,     TEXT ("Help...")) ;
        
           AppendMenu    (hMenu, MF_STRING, IDM_SYS_REMOVE,   TEXT ("Remove Additions")) ;
        
   
        
           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)
        
{
        
   switch (message)
        
           {
        
           case   WM_SYSCOMMAND:
        
                  switch (LOWORD (wParam))
        
                  {
        
                  case   IDM_SYS_ABOUT:
        
                                         MessageBox (  hwnd, TEXT ("A Poor-Person's Menu Program\n")
        
                     TEXT ("(c) Charles Petzold, 1998"),
        
                     szAppName, MB_OK | MB_ICONINFORMATION) ;
        
                                         return 0 ;
        
             
        
                  case   IDM_SYS_HELP:
        
                                         MessageBox (  hwnd, TEXT ("Help not yet implemented!"),
        
                     szAppName, MB_OK | MB_ICONEXCLAMATION) ;
        
                                         return 0 ;
        
             
        
                  case   IDM_SYS_REMOVE:
        
                                         GetSystemMenu (hwnd, TRUE) ;
        
                                         return 0 ;
        
                  }
        
                break ;
        
        
        
                  case   WM_DESTROY:
        
                                  PostQuitMessage (0) ;
        
                                  return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
三个菜单ID在POORMENU.C的开始部分定义:
#define IDM_ABOUT          1
        
#define IDM_HELP           2
        
#define IDM_REMOVE         3
        
在程序窗口建立之后,POORMENU得到一个系统菜单的句柄:
hMenu = GetSystemMenu (hwnd, FALSE) ;
        
第一次呼叫GetSystemMenu时,您应该为修改菜单作准备,将第二个参数设定为FALSE。
使用四个AppendMenu呼叫来实作对菜单的修改:
AppendMenu (hMenu,       MF_SEPARATOR, 0,                                                NULL) ;
        
AppendMenu (hMenu,       MF_STRING, IDM_SYS_ABOUT,     TEXT ("About...")) ;
        
AppendMenu (hMenu,       MF_STRING, IDM_SYS_HELP,             TEXT ("Help...")) ;
        
AppendMenu (hMenu,       MF_STRING, IDM_SYS_REMOVE,    TEXT ("Remove Additions"));
        
第一个AppendMenu呼叫是添加分隔条。选择「Remove Additions」菜单项将使POORMENU删除这些附加的菜单项,这只要把第二个参数设定为TRUE,再次呼叫GetSystemMenu即可:
GetSystemMenu (hwnd, TRUE) ;
        
标准系统菜单有下列选项:Restore、Move、Size、Minimize、Maximize和Close。它们产生wParam分别等于SC_RESTORE、SC_MOVE、SC_SIZE、SC_MINIMUM、SC_MAXIMUM和SC_CLOSE的WM_SYSCOMMAND消息。尽管Windows程序一般不这样做,但是您可以自己处理这些消息,而不把它们留给DefWindowProc。您也可以使用下面所述的方法来禁止或者除掉系统菜单的标准选项。Windows文件中还介绍了一些系统菜单的标准附加项目,这些附加项目使用标识符SC_NEXTWINDOW、SC_PREVWINDOW、SC_VSCROLL、SC_HSCROLL和SC_ARRANGE。您也许会发现,在一些应用程序中将这些命令加入系统菜单是合适的。
