Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1261802
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类: 嵌入式

2012-03-02 12:44:39

 

  1. 上节课我们讲述的是菜单静态加载的办法,除此之外菜单还可以通 过API在程序中动态的创建和加载。

  2. 理论:
  3. 创建普通菜单步骤如下:
  4. 1)创建菜单 如:CreateMenu
  5. 2) 添加菜单项 如:AppendMenu
  6. 3)加载菜单 LoadMenu
  7. 4)设置菜单到窗口 SetMenu
  8. 5)处理菜单响应
  9. 6)消除菜单 DestroyMenu

  10. 创建右键菜单的步骤如下:
  11. 1)创建菜单 如:CreateMenu
  12. 2) 添加菜单项 如:AppendMenu
  13. 3)使用TrackPopupMenu加载菜单。
  14. 4)处理菜单响应
  15. 5)消除菜单 DestroyMenu

  16. 当然,如果你选择在已有菜单上进行编辑的话,也是可以的,就省略了其中的一些步骤。本节的例子就是在已有的菜单里面添加自己定义的菜单 项。对于右键菜单你也可以选择已有的菜单中的一栏作为弹出菜单。
  17. 使用菜单后,要涉及清除的问题,和窗口相连的菜单句柄在窗口摧毁的时候会由Windows自 动释放,不需要手工释放,但没有和窗口相连的菜单就要由程序自己来释放了,方法是使用DestroyMenu函 数,比如没有和窗口相连而仅用TrackPopupMenu弹出的菜单句柄。本例中,我们使用的是窗口关联的菜单句柄,因此我们不需要调用DestroyMenu消除菜单资源。

  18. 菜单消息:
  19. 当用户选择一个菜单项时,windwos通常向窗口过程发送几个不同的消息。在大多数情况下,你的程序可以忽略大部分的 消息,只需要把他们传递给DefWindowProc即可。
  20. 1)WM_INITMENU 消息,wParam :主菜单句柄, lParam : 0
  21. 这个消息是当一个菜单将要激活时发出。当用户点击菜单栏上的项或者 使用菜单键选择 。这个消息允许应用程序在显示之 前修改菜单。可以在这时修改顶层菜单。

  22. 2)WM_MENUSELECT: LOWORD(wParam): 选中项:菜单id或者弹出式菜单句柄。
  23. HIWORD(wParam): 选择标志 lParam: 包含选中项的菜单句柄。
  24. 当用户选择某个菜单项时,这个消息就会被发送到菜单所属的窗口。

  25. 这个消息是一个菜单跟踪消息,wParam告诉你当前选中的是菜单中的哪一项,wParam的高位字中的“选择标志”可以是下列这些标志的组合: MF_GRAYED、MF_DISABLED、MF_CHECKED、MF_BITMAP、MF_POPUP、MF_HELP、MF_SYSMENU和 MF_MOUSESELECT.
  26. 如果你需要根据菜单项的选择来改变窗口客户区的内容,那么可以你可以使用这个消息。

  27. 3)WM_INITMENUPOPUP: wParam: 弹出式菜单句柄
  28. LOWORD(lParam):弹出式菜单索引 HIWORD(lParam):系统菜单为1,其他为0
  29. 如果要在弹出式菜单显示之前启用或者禁用菜单项,那么这个消息就很重要。

  30. 4) WM_COMMAND: LOWORD(wParam): 菜单id
  31. HIWOED(wParam): 0 lParam: 0
  32. 如果这个消息是由子窗口控制产生,如button产生则:
  33. LOWORD(wParam): 控制ID HIWORD(lParam): 通知码 lParam: 子窗口句柄。
  34. 如果这个消息是由子窗口或者快捷键产生,则通知码为1,由菜单产生,通知码为0。
  35. 通过参数,可以区分这个消息的来源是来自于控件,快捷键还是菜单。

  36. 5) WM_SYSCOMMAND: 类似于WM_COMMAND消息,只是WM_SYSCOMMAND表示用户从系统菜单中选择一个启动菜单项或者用户选择最大化,最小化,关闭按钮。
  37. LOWORD(wParam): 菜单id HIWOED(wParam): 0 lParam: 0
  38. 如果消息是由按鼠标产生的,LOWORD(wParam)和HIWORD(lParam)将包含鼠标光标的位置x,y屏幕坐标。
  39. 对于windows预先定义的系统菜单项,用wParam表示。

  40. SC_CLOSE,SC_MAXIMIZE,SC_MINIMIZE,SC_MOVE 等等。

  41. 对于已有菜单,我们可以使用GetSystemMenu,GetMenu ,GetSubMenu来获取菜单句柄。当需要更改菜单时,可以使用下面的API进行更改。 AppendMenu, DeleteMenu,InsertMenu,ModifyMenu,RemoveMenu等等。

  42. 例子:
  43. 接下来,我们看一个例子:(见光盘myMenu)

  44. Menu.rc

  45. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  46. #include “winuser.h”
  47. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  48. #define ICO_MAIN 0×1000 //图标
  49. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  50. #define IDM_MAIN 0×2000 //菜单
  51. #define IDA_MAIN 0×2000 //加速键
  52. #define IDM_OPEN 0×4101
  53. #define IDM_OPTION 0×4102
  54. #define IDM_EXIT 0×4103
  55. #define IDM_SETFONT 0×4201
  56. #define IDM_SETCOLOR 0×4202
  57. #define IDM_INACT 0×4203
  58. #define IDM_GRAY 0×4204
  59. #define IDM_BIG 0×4205
  60. #define IDM_SMALL 0×4206
  61. #define IDM_LIST 0×4207
  62. #define IDM_DETAIL 0×4208
  63. #define IDM_TOOLBAR 0×4209
  64. #define IDM_TOOLBARTEXT 0×4210
  65. #define IDM_INPUTBAR 0×4211
  66. #define IDM_STATUSBAR 0×4212
  67. #define IDM_HELP 0×4301
  68. #define IDM_ABOUT 0×4302
  69. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  70. ICO_MAIN ICON “Main.ico”
  71. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  72. IDM_MAIN menu discardable
  73. BEGIN
  74. popup “文件(&F)
  75. BEGIN
  76. menuitem “打开文件(&O)…”, IDM_OPEN
  77. menuitem “关闭文件(&C)…”, IDM_OPTION
  78. menuitem separator
  79. menuitem “退出(&X), IDM_EXIT
  80. END
  81. popup “查看(&V)
  82. BEGIN
  83. menuitem “字体(&F)\tAlt+F”,IDM_SETFONT
  84. menuitem “背景色(&B)\tCtrl+Alt+B”,IDM_SETCOLOR
  85. menuitem separator
  86. menuitem “被禁用的菜单项”, IDM_INACT, INACTIVE
  87. menuitem “被灰化的菜单项”, IDM_GRAY, GRAYED
  88. menuitem separator
  89. menuitem “大图标(&G), IDM_BIG
  90. menuitem “小图标(&M), IDM_SMALL
  91. menuitem “列表(&L), IDM_LIST
  92. menuitem “详细资料(&D), IDM_DETAIL
  93. menuitem separator
  94. popup “工具栏(&T)
  95. BEGIN
  96. menuitem “标准按钮(&S), IDM_TOOLBAR
  97. menuitem “文字标签(&C), IDM_TOOLBARTEXT
  98. menuitem “命令栏(&I), IDM_INPUTBAR
  99. END
  100. menuitem “状态栏(&U), IDM_STATUSBAR
  101. END
  102. popup “帮助(&H),HELP
  103. BEGIN
  104. menuitem “帮助主题(&H)\tF1″, IDM_HELP
  105. menuitem separator
  106. menuitem “关于本程序(&A)…”,IDM_ABOUT
  107. END
  108. END
  109. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  110. IDA_MAIN accelerators
  111. BEGIN
  112. VK_F1, IDM_HELP, VIRTKEY
  113. “B”, IDM_SETCOLOR,VIRTKEY,CONTROL,ALT
  114. “F”, IDM_SETFONT,VIRTKEY,ALT
  115. END
  116. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  117. main.cpp

  118. #include “windows.h”
  119. #define ICO_MAIN 0×1000 //图标
  120. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  121. #define IDM_MAIN 0×2000 //菜单
  122. #define IDA_MAIN 0×2000 //加速键
  123. #define IDM_OPEN 0×4101
  124. #define IDM_OPTION 0×4102
  125. #define IDM_EXIT 0×4103
  126. #define IDM_SETFONT 0×4201
  127. #define IDM_SETCOLOR 0×4202
  128. #define IDM_INACT 0×4203
  129. #define IDM_GRAY 0×4204
  130. #define IDM_BIG 0×4205
  131. #define IDM_SMALL 0×4206
  132. #define IDM_LIST 0×4207
  133. #define IDM_DETAIL 0×4208
  134. #define IDM_TOOLBAR 0×4209
  135. #define IDM_TOOLBARTEXT 0×4210
  136. #define IDM_INPUTBAR 0×4211
  137. #define IDM_STATUSBAR 0×4212
  138. #define IDM_HELP 0×4301
  139. #define IDM_ABOUT 0×4302

  140. char szClassName[] = “Menu Example”;
  141. char szCaptionMain[] = “menu”;
  142. char szMenuHelp[] = “帮助主题(&H);
  143. char szMenuAbout[] = “关于本程序(&A)…”;
  144. char szCaption[] = “菜单选择”;
  145. char szFormat[] = “您选择了菜单命令:%08x”;
  146. HWND g_hWinMain;
  147. HMENU g_hMenu;
  148. HMENU g_hSubMenu;
  149. HINSTANCE g_hInstance;

  150. void DisplayMenuItem(DWORD dwCommandID)
  151. {
  152. char szBuffer[256] = {0};
  153. wsprintf(szBuffer,szFormat,dwCommandID);
  154. MessageBox(g_hWinMain,szBuffer,szCaption,MB_OK);
  155. }

  156. void Quit()
  157. {

  158. DestroyWindow(g_hWinMain);
  159. PostQuitMessage(NULL);
  160. }

  161. LRESULT CALLBACK ProcWinMain(HWND hWnd,UINT uMsg,WPARAM wParam ,LPARAM lParam)
  162. {
  163. POINT stPos;
  164. HMENU hSysMenu;

  165. switch(uMsg)
  166. {
  167. case WM_CREATE:
  168. g_hSubMenu = GetSubMenu(g_hMenu,1);
  169. hSysMenu = GetSystemMenu(hWnd,FALSE);
  170. AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL);
  171. AppendMenu(hSysMenu,0,IDM_HELP,szMenuHelp);
  172. AppendMenu(hSysMenu,0,IDM_ABOUT,szMenuAbout);
  173. break;

  174. case WM_COMMAND:
  175. DisplayMenuItem(wParam);
  176. if(LOWORD(wParam) == IDM_EXIT)
  177. Quit();
  178. else if(LOWORD(wParam) >= IDM_TOOLBAR &&
  179. LOWORD(wParam) <= IDM_STATUSBAR)
  180. {
  181. UINT uState = GetMenuState(g_hMenu,LOWORD(wParam),MF_BYCOMMAND);
  182. if(uState == MF_CHECKED)
  183. uState = MF_UNCHECKED;
  184. else
  185. uState = MF_CHECKED;

  186. CheckMenuItem(g_hMenu,LOWORD(wParam),uState);
  187. }
  188. else if(LOWORD(wParam) >= IDM_BIG &&
  189. LOWORD(wParam) <= IDM_DETAIL)
  190. {
  191. CheckMenuRadioItem(g_hMenu,IDM_BIG,IDM_DETAIL,LOWORD(wParam),MF_BYCOMMAND);
  192. }
  193. break;

  194. case WM_SYSCOMMAND:
  195. if(LOWORD(wParam) == IDM_HELP ||
  196. LOWORD(wParam) == IDM_ABOUT)
  197. DisplayMenuItem(wParam);
  198. else
  199. return DefWindowProc(hWnd,uMsg,wParam,lParam);
  200. break;

  201. case WM_RBUTTONDOWN:
  202. GetCursorPos(&stPos);
  203. TrackPopupMenu(g_hSubMenu,TPM_LEFTALIGN,stPos.x,
  204. stPos.y,NULL,hWnd,NULL);
  205. break;

  206. case WM_CLOSE:
  207. Quit();
  208. break;

  209. default:
  210. return DefWindowProc(hWnd,uMsg,wParam,lParam);

  211. }

  212. return 0;
  213. }

  214. int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
  215. {
  216. MSG msg;
  217. WNDCLAS*** stWndClass;
  218. HACCEL hAccelerator;
  219. g_hInstance = hInstance;
  220. g_hMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDM_MAIN));
  221. hAccelerator = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDA_MAIN));

  222. RtlZeroMemory(&stWndClass,sizeof(stWndClass));
  223. stWndClass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(ICO_MAIN));
  224. stWndClass.hIconSm = stWndClass.hIcon;
  225. stWndClass.hCursor = LoadCursor(0,IDC_ARROW);
  226. stWndClass.hInstance = hInstance;
  227. stWndClass.cbSize = sizeof(WNDCLAS***);
  228. stWndClass.style = CS_HREDRAW|CS_VREDRAW;
  229. stWndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  230. stWndClass.lpfnWndProc = ProcWinMain;
  231. stWndClass.lpszClassName = szClassName;

  232. RegisterClas***(&stWndClass);

  233. g_hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,
  234. szCaptionMain,WS_OVERLAPPEDWINDOW,100,100,400,300,
  235. NULL,g_hMenu,hInstance,NULL);

  236. if(!g_hWinMain)
  237. return 0;

  238. ShowWindow(g_hWinMain,SW_SHOWNORMAL);
  239. UpdateWindow(g_hWinMain);

  240. while(GetMessage(&msg,NULL,0,0))
  241. {
  242. if(!TranslateAccelerator(g_hWinMain,hAccelerator,&msg))
  243. {
  244. TranslateMessage(&msg);
  245. DispatchMessage(&msg);
  246. }

  247. }
  248. return msg.wParam;
  249. }

  250. 分析:在这个例子中我们是采用编程的方法实现菜单加载和创建的。
  251. case WM_CREATE:
  252. g_hSubMenu = GetSubMenu(g_hMenu,1);
  253. hSysMenu = GetSystemMenu(hWnd,FALSE);
  254. AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL);
  255. AppendMenu(hSysMenu,0,IDM_HELP,szMenuHelp);
  256. AppendMenu(hSysMenu,0,IDM_ABOUT,szMenuAbout);
  257. break;

  258. 在WM_CREATE 消息中处理菜单。在这里,我们是直接在原有的系统菜单上添加自己定义的菜单项,因此,我们不需要处理加载菜单的事情。当在 WinMain函数中调用CreateWindowEx创建窗口的时候,就产生了WM_CREATE消息。此时窗口还没有显示,所以我们在这里添加菜单 项。

  259. g_hSubMenu = GetSubMenu(g_hMenu,1);

  260. 用于获取菜单中的第一栏子菜单 句柄,后面把这一栏子菜单用作弹出菜单。

  261. hSysMenu = GetSystemMenu(hWnd,FALSE);

  262. 获取当前加载的系统菜单,后面 我们把自己的菜单加载到系统菜单上。对于系统菜单,相应的消息是WM_SYSCOMMAND,我们自己定义的菜单响应的消息是WM_COMMAND。

  263. case WM_RBUTTONDOWN:
  264. GetCursorPos(&stPos);
  265. TrackPopupMenu(g_hSubMenu,TPM_LEFTALIGN,stPos.x,
  266. stPos.y,NULL,hWnd,NULL);
  267. break;

  268. 当点击鼠标右键的时候,响应 WM_RBUTTONDOWN消息,弹出右键菜单项。GetCursorPos获取当前鼠标点击位置。

  269. case WM_COMMAND:
  270. DisplayMenuItem(wParam);
  271. if(LOWORD(wParam) == IDM_EXIT)
  272. Quit();
  273. else if(LOWORD(wParam) >= IDM_TOOLBAR &&
  274. LOWORD(wParam) <= IDM_STATUSBAR)
  275. {
  276. UINT uState = GetMenuState(g_hMenu,LOWORD(wParam),MF_BYCOMMAND);
  277. if(uState == MF_CHECKED)
  278. uState = MF_UNCHECKED;
  279. else
  280. uState = MF_CHECKED;

  281. CheckMenuItem(g_hMenu,LOWORD(wParam),uState);
  282. }
  283. else if(LOWORD(wParam) >= IDM_BIG &&
  284. LOWORD(wParam) <= IDM_DETAIL)
  285. {
  286. CheckMenuRadioItem(g_hMenu,IDM_BIG,IDM_DETAIL,LOWORD(wParam),MF_BYCOMMAND);
  287. }
  288. break;

  289. CheckMenuItem,CheckMenuRadioItem 分别用于改变菜单项的状态。菜单项的状态可以通过GetMenuState函数获得。这三个函数的详细介绍可以看 msdn。

 

http://hi.baidu.com/a1140314368/blog/item/a7b7202b51579e4b4fc22692.html

阅读(935) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

鱼门客栈2012-03-03 08:38:14

恩,认真学习了1!