/*----------------------------------------------------------------------
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) ;
}
卷动列控件不向父窗口发送WM_COMMAND消息,而是像窗口卷动列那样发送WM_VSCROLL和WM_HSCROLL消息。在处理卷动消息时,您可以通过lParam参数来区分窗口卷动列与卷动列控件。对子窗口卷动列其值为0,对于卷动列控件其值为卷动列窗口代号。对窗口卷动列和卷动列控件来说,wParam参数的高字组和低字组的含义相同。
选中了 Pop-up 复选框,该项目就会调用一个突现式菜单,并且没有ID与此项目相联系。如果没有选中 Pop-up 复选框,该项目被选中时就会产生带有特定ID的WM_COMMAND消息。这两类菜单项分别出现在资源描述档的POPUP和MENUITEM叙述中。
在程序中引用菜单1.大多数Windows应用程序在资源描述文件中只有一个菜单。您可以给菜单起一个与程序名称相同的文字的名称。程序编写者经常将程序名用于菜单名称,以便相同的字符串可以用于窗口类别、程序的图标名称和菜单名称。然后,程序在窗口的定义中为菜单引用该名称:
wndclass.lpszMenuName = szAppName ;
2.Windows应用程序可以使用LoadMenu函数将菜单资源调入内存中,如同LoadIcon和LoadCursor函数一样。LoadMenu传回一个菜单代号。如果您在资源描述文件中为菜单使用了名称,叙述如下:
hMenu = LoadMenu (hInstance, TEXT ("MyMenu")) ; //命名id时加“MyMenu”
如果使用了数值,那么LoadMenu调用采用如下的形式:
hMenu = LoadMenu (hInstance, MAKEINTRESOURCE (ID_MENU)) ;
然后,您可以将这个菜单代号作为CreateWindow的第九个参数:
hwnd = CreateWindow ( TEXT ("MyClass"), TEXT ("Window Caption"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, hMenu, hInstance, NULL) ;
在这种情况下,CreateWindow调用中指定的菜单可以覆盖窗口类别中指定的任何菜单。如果CreateWindow的第九个参数是NULL,那么您可以把窗口类别中的菜单看作是这种窗口类别的窗口内定使用的菜单。这样,您可以为依据同一窗口类别建立的几个窗口使用不同的菜单。
3.您也可以在窗口类别中指定NULL菜单,并且在CreateWindow调用中也指定NULL菜单,然后在窗口被建立后再给窗口指定一个菜单:
SetMenu (hwnd, hMenu) ;
这种形式使您可以动态地修改窗口的菜单。在本章后面的 NOPOPUPS程序 中我们将会看到这方面的例子。
当窗口被清除时,与窗口相关的所有菜单都将被清除。与窗口不相关的菜单在程序结束前通过调用DestroyMenu主动清除。
/*-------------------------------------------------------------------------- ICONDEMO.C -- Icon Demonstration Program (c) Charles Petzold, 1998 --------------------------------------------------------------------------*/ #include <windows.h> #include "resource.h" #define ID_TIMER 1 TCHAR szAppName[] = TEXT("MENUDEMO"); HINSTANCE hlnst; LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { // TCHAR szAppName[] = TEXT ("ICONDEMO") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; HMENU hMenu; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON)) ; wndclass.hCursor = LoadCursor (hInstance, MAKEINTRESOURCE(IDC_CURSOR));//IDC_ARROW) ; wndclass.hbrBackground =(HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL;//szAppName ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox ( NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hlnst = hInstance; hwnd = CreateWindow ( szAppName, TEXT ("Icon Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL//MAKEINTRESOURCE (MyMenu)) , hInstance, NULL) ; //SetMenu(hwnd, LoadMenu (hInstance, L"ICONDEMO")); 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 HICON hIcon ; static int cxIcon, cyIcon, cxClient, cyClient ; HDC hdc ; HINSTANCE hInstance ; PAINTSTRUCT ps ; int x, y ; 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_COMMAND: hMenu = GetMenu(hwnd); switch(LOWORD(wParam)) { case IDM_FILE_NEW: case IDM_FILE_OPEN: case IDM_FILE_SAVE: case IDM_FILE_SAVE_AS: MessageBeep(0); return 0; case IDM_APP_EXIT: SendMessage(hwnd, WM_CLOSE, 0, 0); return 0; 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_TIMER_START: if(SetTimer(hwnd, ID_TIMER, 10000,NULL)) { EnableMenuItem(hMenu, IDM_TIMER_START, MF_GRAYED); EnableMenuItem(hMenu, IDM_TIMER_STOP, MF_ENABLED); } return 0; case IDM_TIMER_STOP: KillTimer(hwnd, ID_TIMER); EnableMenuItem(hMenu, IDM_TIMER_START, MF_ENABLED); EnableMenuItem(hMenu, IDM_TIMER_STOP, MF_GRAYED); return 0; case IDM_APP_HELP: MessageBox(hwnd, TEXT("Help not yet implemented"), szAppName,MB_ICONEXCLAMATION | MB_OK ); return 0; case IDM_APP_ABOUT: MessageBox(hwnd, TEXT("MENU DEMONSTRATION")TEXT ("(c) Charles Petzold, 1998"), szAppName, MB_ICONINFORMATION | MB_OK); return 0; } break; case WM_CREATE : hInstance = ((LPCREATESTRUCT) lParam)->hInstance ; hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON)) ; cxIcon = GetSystemMetrics (SM_CXICON) ; cyIcon = GetSystemMetrics (SM_CYICON) ; hMenu = LoadMenu(hlnst,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_SIZE : cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; return 0 ; /*case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; for (y = 0 ; y < cyClient ; y += cyIcon) for (x = 0 ; x < cxClient ; x += cxIcon) DrawIcon (hdc, x, y, hIcon) ; EndPaint (hwnd, &ps) ; return 0 ; */ case WM_TIMER: MessageBeep(0); return 0; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }