二、Windows菜单—浮动弹出式菜单
您还可以在没有顶层菜单列的情况下使用菜单,也就是说,您可以使弹出式菜单出现在屏幕顶层的任何位置。一种方法是使用鼠标右键来启动弹出式菜单。程序10-6所示的POPMENU说明了这种方法。
        
POPMENU.C
        
/*----------------------------------------------------------------------
        
  POPMENU.C -- Popup Menu Demonstration
        
                                                 (c) Charles Petzold, 1998
        
-------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include "resource.h"
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
HINSTANCE hInst ;
        
TCHAR              szAppName[] = TEXT ("PopMenu") ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                         PSTR szCmdLine, int iCmdShow)
        
{
        
           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, szAppName) ;
        
           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 ;
        
    }
        
   
        
           hInst = hInstance ;
        
           hwnd = CreateWindow ( szAppName, TEXT ("Popup 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  hMenu ;
        
           static int            idColor [5] = {WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH,
        
                                         DKGRAY_BRUSH, BLACK_BRUSH } ;
        
           static int            iSelection    = IDM_BKGND_WHITE ;
        
           POINT                                point ;
        
   
        
           switch (message)
        
    {
        
           case   WM_CREATE:
        
                  hMenu = LoadMenu (hInst, szAppName) ;
        
                  hMenu = GetSubMenu (hMenu, 0) ;
        
                  return 0 ;
        
          case   WM_RBUTTONUP:
        
                  point.x = LOWORD (lParam) ;
        
                  point.y = HIWORD (lParam) ;
        
                  ClientToScreen (hwnd, &point) ;
        
        
        
                  TrackPopupMenu (hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL) ;
        
                  return 0 ;
        
        
        
           case   WM_COMMAND:
        
                  switch (LOWORD (wParam))
        
                  {
        
                  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 ;
        
             
        
                  case   IDM_BKGND_WHITE:              // Note: Logic below
        
                 case   IDM_BKGND_LTGRAY:             //   assumes that IDM_WHITE
        
                  case   IDM_BKGND_GRAY:               //   through IDM_BLACK are
        
                  case   IDM_BKGND_DKGRAY:             //   consecutive numbers in
        
                  case   IDM_BKGND_BLACK:            //   the order shown here.
        
             
        
                                         CheckMenuItem (hMenu, iSelection, MF_UNCHECKED) ;
        
                                         iSelection = LOWORD (wParam) ;
        
                                         CheckMenuItem (hMenu, iSelection, MF_CHECKED) ;
        
             
        
                                        SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)
        
                                                               GetStockObject
        
                           (idColor [LOWORD (wParam) - IDM_BKGND_WHITE])) ;
        
             
        
                                         InvalidateRect (hwnd, NULL, TRUE) ;
        
                                        return 0 ;
        
             
        
                  case   IDM_APP_ABOUT:
        
                                         MessageBox (hwnd, TEXT ("Popup Menu Demonstration Program\n")
        
                          TEXT ("(c) Charles Petzold, 1998"),
        
                                  szAppName, MB_ICONINFORMATION | MB_OK) ;
        
                                  return 0 ;
        
             
        
                  case   IDM_APP_EXIT:
        
                                         SendMessage (hwnd, WM_CLOSE, 0, 0) ;
        
                                         return 0 ;
        
             
        
                  case   IDM_APP_HELP:
        
                                        MessageBox (hwnd, TEXT ("Help not yet implemented!"),
        
                           szAppName, MB_ICONEXCLAMATION | MB_OK) ;
        
                                         return 0 ;
        
                  }
        
                  break ;
        
        
        
           case   WM_DESTROY:
        
                  PostQuitMessage (0) ;
        
                  return 0 ;
        
    }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
        
//Microsoft Developer Studio generated resource script.
        
#include "resource.h"
        
#include "afxres.h"
        
/////////////////////////////////////////////////////////////////////////////
        
// Menu
        
POPMENU MENU DISCARDABLE
        
BEGIN
        
   POPUP "MyMenu"
        
   BEGIN
        
                  POPUP "&File"
        
                  BEGIN
        
                  MENUITEM "&New",                             IDM_FILE_NEW
        
                  MENUITEM "&Open",                    IDM_FILE_OPEN
        
                  MENUITEM "&Save",                     IDM_FILE_SAVE
        
                  MENUITEM "Save &As",     IDM_FILE_SAVE_AS
        
                  MENUITEM SEPARATOR
        
                  MENUITEM "E&xit",                    IDM_APP_EXIT
        
                 END
        
                  POPUP "&Edit"
        
                  BEGIN
        
                          MENUITEM "&Undo",             IDM_EDIT_UNDO
        
                          MENUITEM SEPARATOR
        
                          MENUITEM "Cu&t",              IDM_EDIT_CUT
        
                          MENUITEM "&Copy",             IDM_EDIT_COPY
        
                          MENUITEM "&Paste",            IDM_EDIT_PASTE
        
                          MENUITEM "De&lete",           IDM_EDIT_CLEAR
        
END
        
    POPUP "&Background"
        
BEGIN
        
   MENUITEM "&White",                    IDM_BKGND_WHITE, CHECKED
        
MENUITEM "&Light Gray",       IDM_BKGND_LTGRAY
        
MENUITEM "&Gray",                         IDM_BKGND_GRAY
        
MENUITEM "&Dark Gray",             IDM_BKGND_DKGRAY
        
MENUITEM "&Black",                 IDM_BKGND_BLACK
        
END
        
    POPUP "&Help"
        
BEGIN
        
MENUITEM "&Help...",               IDM_APP_HELP
        
    MENUITEM "&About PopMenu...", IDM_APP_ABOUT
        
END
        
  END
        
END
        
        
// Microsoft Developer Studio generated include file.
        
// Used by PopMenu.rc
        
#define IDM_FILE_NEW                  40001
        
#define IDM_FILE_OPEN                 40002
        
#define IDM_FILE_SAVE                 40003
        
#define IDM_FILE_SAVE_AS              40004
        
#define IDM_APP_EXIT                  40005
        
#define IDM_EDIT_UNDO                 40006
        
#define IDM_EDIT_CUT                40007
        
#define IDM_EDIT_COPY                 40008
        
#define IDM_EDIT_PASTE                40009
        
#define IDM_EDIT_CLEAR                40010
        
#define IDM_BKGND_WHITE               40011
        
#define IDM_BKGND_LTGRAY              40012
        
#define IDM_BKGND_GRAY                40013
        
#define IDM_BKGND_DKGRAY              40014
        
#define IDM_BKGND_BLACK               40015
        
#define IDM_APP_HELP                  40016
        
#define IDM_APP_ABOUT                 40017
        
资源描述档POPMENU.RC定义的菜单与MENUDEMO.RC中的菜单非常相似。不同的是,在顶层菜单中只包含一项-一个弹出式菜单「MyMenu」,它呼叫「File」、「Edit」、「Background」和「Help」选项。这四个选项垂直一行地出现在弹出式菜单上,而不是水平一列地出现在主菜单上。
在WndProc中的WM_CREATE处理期间,POPMENU取得此弹出式菜单的句柄,就是带有文字「MyMenu」的那个弹出式菜单:
hMenu = LoadMenu (hInst, szAppName) ;
        
hMenu = GetSubMenu (hMenu, 0) ;
        
在WM_RBUTTONUP消息处理期间,POPMENU提供了鼠标指针的位置,将此位置转换为屏幕坐标,再将坐标值传递给TrackPopupMenu:
point.x = LOWORD (lParam) ;
        
point.y = HIWORD (lParam) ;
        
ClientToScreen (hwnd, &point) ;
        
TrackPopupMenu (hMenu, TPM_RIGHTBUTTON, point.x, point.y,
        
                                                 0, hwnd, NULL) ;
        
然后,Windows显示出具有「File」、「Edit」、「Background」和「Help」项的弹出式菜单。选择其中任何一项都可以使嵌套的弹出式菜单显示在右边,菜单函数与一般的菜单一样。
如果要使用与该程序的主菜单相同的菜单并带有TrackPopupMenu,您会遇到一些问题,因为函数需要弹出式菜单句柄。在「Microsoft Knowledge Base」文章ID Q99806有提供一些信息。
