- 上节课我们讲述的是菜单静态加载的办法,除此之外菜单还可以通 过API在程序中动态的创建和加载。
- 理论:
- 创建普通菜单步骤如下:
- 1)创建菜单 如:CreateMenu
- 2) 添加菜单项 如:AppendMenu
- 3)加载菜单 LoadMenu
- 4)设置菜单到窗口 SetMenu
- 5)处理菜单响应
- 6)消除菜单 DestroyMenu
- 创建右键菜单的步骤如下:
- 1)创建菜单 如:CreateMenu
- 2) 添加菜单项 如:AppendMenu
- 3)使用TrackPopupMenu加载菜单。
- 4)处理菜单响应
- 5)消除菜单 DestroyMenu
- 当然,如果你选择在已有菜单上进行编辑的话,也是可以的,就省略了其中的一些步骤。本节的例子就是在已有的菜单里面添加自己定义的菜单 项。对于右键菜单你也可以选择已有的菜单中的一栏作为弹出菜单。
- 使用菜单后,要涉及清除的问题,和窗口相连的菜单句柄在窗口摧毁的时候会由Windows自 动释放,不需要手工释放,但没有和窗口相连的菜单就要由程序自己来释放了,方法是使用DestroyMenu函 数,比如没有和窗口相连而仅用TrackPopupMenu弹出的菜单句柄。本例中,我们使用的是窗口关联的菜单句柄,因此我们不需要调用DestroyMenu消除菜单资源。
- 菜单消息:
- 当用户选择一个菜单项时,windwos通常向窗口过程发送几个不同的消息。在大多数情况下,你的程序可以忽略大部分的 消息,只需要把他们传递给DefWindowProc即可。
- 1)WM_INITMENU 消息,wParam :主菜单句柄, lParam : 0
- 这个消息是当一个菜单将要激活时发出。当用户点击菜单栏上的项或者 使用菜单键选择 。这个消息允许应用程序在显示之 前修改菜单。可以在这时修改顶层菜单。
- 2)WM_MENUSELECT: LOWORD(wParam): 选中项:菜单id或者弹出式菜单句柄。
- HIWORD(wParam): 选择标志 lParam: 包含选中项的菜单句柄。
- 当用户选择某个菜单项时,这个消息就会被发送到菜单所属的窗口。
- 这个消息是一个菜单跟踪消息,wParam告诉你当前选中的是菜单中的哪一项,wParam的高位字中的“选择标志”可以是下列这些标志的组合: MF_GRAYED、MF_DISABLED、MF_CHECKED、MF_BITMAP、MF_POPUP、MF_HELP、MF_SYSMENU和 MF_MOUSESELECT.
- 如果你需要根据菜单项的选择来改变窗口客户区的内容,那么可以你可以使用这个消息。
- 3)WM_INITMENUPOPUP: wParam: 弹出式菜单句柄
- LOWORD(lParam):弹出式菜单索引 HIWORD(lParam):系统菜单为1,其他为0
- 如果要在弹出式菜单显示之前启用或者禁用菜单项,那么这个消息就很重要。
- 4) WM_COMMAND: LOWORD(wParam): 菜单id
- HIWOED(wParam): 0 lParam: 0
- 如果这个消息是由子窗口控制产生,如button产生则:
- LOWORD(wParam): 控制ID HIWORD(lParam): 通知码 lParam: 子窗口句柄。
- 如果这个消息是由子窗口或者快捷键产生,则通知码为1,由菜单产生,通知码为0。
- 通过参数,可以区分这个消息的来源是来自于控件,快捷键还是菜单。
- 5) WM_SYSCOMMAND: 类似于WM_COMMAND消息,只是WM_SYSCOMMAND表示用户从系统菜单中选择一个启动菜单项或者用户选择最大化,最小化,关闭按钮。
- LOWORD(wParam): 菜单id HIWOED(wParam): 0 lParam: 0
- 如果消息是由按鼠标产生的,LOWORD(wParam)和HIWORD(lParam)将包含鼠标光标的位置x,y屏幕坐标。
- 对于windows预先定义的系统菜单项,用wParam表示。
- SC_CLOSE,SC_MAXIMIZE,SC_MINIMIZE,SC_MOVE 等等。
- 对于已有菜单,我们可以使用GetSystemMenu,GetMenu ,GetSubMenu来获取菜单句柄。当需要更改菜单时,可以使用下面的API进行更改。 AppendMenu, DeleteMenu,InsertMenu,ModifyMenu,RemoveMenu等等。
- 例子:
- 接下来,我们看一个例子:(见光盘myMenu)
- Menu.rc
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- #include “winuser.h”
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- #define ICO_MAIN 0×1000 //图标
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- #define IDM_MAIN 0×2000 //菜单
- #define IDA_MAIN 0×2000 //加速键
- #define IDM_OPEN 0×4101
- #define IDM_OPTION 0×4102
- #define IDM_EXIT 0×4103
- #define IDM_SETFONT 0×4201
- #define IDM_SETCOLOR 0×4202
- #define IDM_INACT 0×4203
- #define IDM_GRAY 0×4204
- #define IDM_BIG 0×4205
- #define IDM_SMALL 0×4206
- #define IDM_LIST 0×4207
- #define IDM_DETAIL 0×4208
- #define IDM_TOOLBAR 0×4209
- #define IDM_TOOLBARTEXT 0×4210
- #define IDM_INPUTBAR 0×4211
- #define IDM_STATUSBAR 0×4212
- #define IDM_HELP 0×4301
- #define IDM_ABOUT 0×4302
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- ICO_MAIN ICON “Main.ico”
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- IDM_MAIN menu discardable
- BEGIN
- popup “文件(&F)”
- BEGIN
- menuitem “打开文件(&O)…”, IDM_OPEN
- menuitem “关闭文件(&C)…”, IDM_OPTION
- menuitem separator
- menuitem “退出(&X)”, IDM_EXIT
- END
- popup “查看(&V)”
- BEGIN
- menuitem “字体(&F)…\tAlt+F”,IDM_SETFONT
- menuitem “背景色(&B)…\tCtrl+Alt+B”,IDM_SETCOLOR
- menuitem separator
- menuitem “被禁用的菜单项”, IDM_INACT, INACTIVE
- menuitem “被灰化的菜单项”, IDM_GRAY, GRAYED
- menuitem separator
- menuitem “大图标(&G)”, IDM_BIG
- menuitem “小图标(&M)”, IDM_SMALL
- menuitem “列表(&L)”, IDM_LIST
- menuitem “详细资料(&D)”, IDM_DETAIL
- menuitem separator
- popup “工具栏(&T)”
- BEGIN
- menuitem “标准按钮(&S)”, IDM_TOOLBAR
- menuitem “文字标签(&C)”, IDM_TOOLBARTEXT
- menuitem “命令栏(&I)”, IDM_INPUTBAR
- END
- menuitem “状态栏(&U)”, IDM_STATUSBAR
- END
- popup “帮助(&H)” ,HELP
- BEGIN
- menuitem “帮助主题(&H)\tF1″, IDM_HELP
- menuitem separator
- menuitem “关于本程序(&A)…”,IDM_ABOUT
- END
- END
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- IDA_MAIN accelerators
- BEGIN
- VK_F1, IDM_HELP, VIRTKEY
- “B”, IDM_SETCOLOR,VIRTKEY,CONTROL,ALT
- “F”, IDM_SETFONT,VIRTKEY,ALT
- END
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- main.cpp
- #include “windows.h”
- #define ICO_MAIN 0×1000 //图标
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- #define IDM_MAIN 0×2000 //菜单
- #define IDA_MAIN 0×2000 //加速键
- #define IDM_OPEN 0×4101
- #define IDM_OPTION 0×4102
- #define IDM_EXIT 0×4103
- #define IDM_SETFONT 0×4201
- #define IDM_SETCOLOR 0×4202
- #define IDM_INACT 0×4203
- #define IDM_GRAY 0×4204
- #define IDM_BIG 0×4205
- #define IDM_SMALL 0×4206
- #define IDM_LIST 0×4207
- #define IDM_DETAIL 0×4208
- #define IDM_TOOLBAR 0×4209
- #define IDM_TOOLBARTEXT 0×4210
- #define IDM_INPUTBAR 0×4211
- #define IDM_STATUSBAR 0×4212
- #define IDM_HELP 0×4301
- #define IDM_ABOUT 0×4302
- char szClassName[] = “Menu Example”;
- char szCaptionMain[] = “menu”;
- char szMenuHelp[] = “帮助主题(&H)”;
- char szMenuAbout[] = “关于本程序(&A)…”;
- char szCaption[] = “菜单选择”;
- char szFormat[] = “您选择了菜单命令:%08x”;
- HWND g_hWinMain;
- HMENU g_hMenu;
- HMENU g_hSubMenu;
- HINSTANCE g_hInstance;
- void DisplayMenuItem(DWORD dwCommandID)
- {
- char szBuffer[256] = {0};
- wsprintf(szBuffer,szFormat,dwCommandID);
- MessageBox(g_hWinMain,szBuffer,szCaption,MB_OK);
- }
- void Quit()
- {
- DestroyWindow(g_hWinMain);
- PostQuitMessage(NULL);
- }
- LRESULT CALLBACK ProcWinMain(HWND hWnd,UINT uMsg,WPARAM wParam ,LPARAM lParam)
- {
- POINT stPos;
- HMENU hSysMenu;
- switch(uMsg)
- {
- case WM_CREATE:
- g_hSubMenu = GetSubMenu(g_hMenu,1);
- hSysMenu = GetSystemMenu(hWnd,FALSE);
- AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL);
- AppendMenu(hSysMenu,0,IDM_HELP,szMenuHelp);
- AppendMenu(hSysMenu,0,IDM_ABOUT,szMenuAbout);
- break;
- case WM_COMMAND:
- DisplayMenuItem(wParam);
- if(LOWORD(wParam) == IDM_EXIT)
- Quit();
- else if(LOWORD(wParam) >= IDM_TOOLBAR &&
- LOWORD(wParam) <= IDM_STATUSBAR)
- {
- UINT uState = GetMenuState(g_hMenu,LOWORD(wParam),MF_BYCOMMAND);
- if(uState == MF_CHECKED)
- uState = MF_UNCHECKED;
- else
- uState = MF_CHECKED;
- CheckMenuItem(g_hMenu,LOWORD(wParam),uState);
- }
- else if(LOWORD(wParam) >= IDM_BIG &&
- LOWORD(wParam) <= IDM_DETAIL)
- {
- CheckMenuRadioItem(g_hMenu,IDM_BIG,IDM_DETAIL,LOWORD(wParam),MF_BYCOMMAND);
- }
- break;
- case WM_SYSCOMMAND:
- if(LOWORD(wParam) == IDM_HELP ||
- LOWORD(wParam) == IDM_ABOUT)
- DisplayMenuItem(wParam);
- else
- return DefWindowProc(hWnd,uMsg,wParam,lParam);
- break;
- case WM_RBUTTONDOWN:
- GetCursorPos(&stPos);
- TrackPopupMenu(g_hSubMenu,TPM_LEFTALIGN,stPos.x,
- stPos.y,NULL,hWnd,NULL);
- break;
- case WM_CLOSE:
- Quit();
- break;
- default:
- return DefWindowProc(hWnd,uMsg,wParam,lParam);
- }
- return 0;
- }
- int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
- {
- MSG msg;
- WNDCLAS*** stWndClass;
- HACCEL hAccelerator;
- g_hInstance = hInstance;
- g_hMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDM_MAIN));
- hAccelerator = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDA_MAIN));
- RtlZeroMemory(&stWndClass,sizeof(stWndClass));
- stWndClass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(ICO_MAIN));
- stWndClass.hIconSm = stWndClass.hIcon;
- stWndClass.hCursor = LoadCursor(0,IDC_ARROW);
- stWndClass.hInstance = hInstance;
- stWndClass.cbSize = sizeof(WNDCLAS***);
- stWndClass.style = CS_HREDRAW|CS_VREDRAW;
- stWndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- stWndClass.lpfnWndProc = ProcWinMain;
- stWndClass.lpszClassName = szClassName;
- RegisterClas***(&stWndClass);
- g_hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,
- szCaptionMain,WS_OVERLAPPEDWINDOW,100,100,400,300,
- NULL,g_hMenu,hInstance,NULL);
- if(!g_hWinMain)
- return 0;
- ShowWindow(g_hWinMain,SW_SHOWNORMAL);
- UpdateWindow(g_hWinMain);
- while(GetMessage(&msg,NULL,0,0))
- {
- if(!TranslateAccelerator(g_hWinMain,hAccelerator,&msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- return msg.wParam;
- }
- 分析:在这个例子中我们是采用编程的方法实现菜单加载和创建的。
- case WM_CREATE:
- g_hSubMenu = GetSubMenu(g_hMenu,1);
- hSysMenu = GetSystemMenu(hWnd,FALSE);
- AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL);
- AppendMenu(hSysMenu,0,IDM_HELP,szMenuHelp);
- AppendMenu(hSysMenu,0,IDM_ABOUT,szMenuAbout);
- break;
- 在WM_CREATE 消息中处理菜单。在这里,我们是直接在原有的系统菜单上添加自己定义的菜单项,因此,我们不需要处理加载菜单的事情。当在 WinMain函数中调用CreateWindowEx创建窗口的时候,就产生了WM_CREATE消息。此时窗口还没有显示,所以我们在这里添加菜单 项。
- g_hSubMenu = GetSubMenu(g_hMenu,1);
- 用于获取菜单中的第一栏子菜单 句柄,后面把这一栏子菜单用作弹出菜单。
- hSysMenu = GetSystemMenu(hWnd,FALSE);
- 获取当前加载的系统菜单,后面 我们把自己的菜单加载到系统菜单上。对于系统菜单,相应的消息是WM_SYSCOMMAND,我们自己定义的菜单响应的消息是WM_COMMAND。
- case WM_RBUTTONDOWN:
- GetCursorPos(&stPos);
- TrackPopupMenu(g_hSubMenu,TPM_LEFTALIGN,stPos.x,
- stPos.y,NULL,hWnd,NULL);
- break;
- 当点击鼠标右键的时候,响应 WM_RBUTTONDOWN消息,弹出右键菜单项。GetCursorPos获取当前鼠标点击位置。
- case WM_COMMAND:
- DisplayMenuItem(wParam);
- if(LOWORD(wParam) == IDM_EXIT)
- Quit();
- else if(LOWORD(wParam) >= IDM_TOOLBAR &&
- LOWORD(wParam) <= IDM_STATUSBAR)
- {
- UINT uState = GetMenuState(g_hMenu,LOWORD(wParam),MF_BYCOMMAND);
- if(uState == MF_CHECKED)
- uState = MF_UNCHECKED;
- else
- uState = MF_CHECKED;
- CheckMenuItem(g_hMenu,LOWORD(wParam),uState);
- }
- else if(LOWORD(wParam) >= IDM_BIG &&
- LOWORD(wParam) <= IDM_DETAIL)
- {
- CheckMenuRadioItem(g_hMenu,IDM_BIG,IDM_DETAIL,LOWORD(wParam),MF_BYCOMMAND);
- }
- break;
- CheckMenuItem,CheckMenuRadioItem 分别用于改变菜单项的状态。菜单项的状态可以通过GetMenuState函数获得。这三个函数的详细介绍可以看 msdn。
http://hi.baidu.com/a1140314368/blog/item/a7b7202b51579e4b4fc22692.html
阅读(970) | 评论(1) | 转发(0) |