Windows窗口菜单的消息顺序和WM_EXITMENULOOP

简介:

 Windows的窗口菜单是一个比较常用的资源,通常的做法都是在先创建菜单,然后鼠标点击窗口的某个位置时显示菜单,然后点击菜单项,向窗口发送WM_COMMAND消息.如下代码片段所示:

 
  1. ... 
  2. m_hWinMenu = ::LoadMenu(::GetInstance(), MAKEINTRESOURCE(IDM_MAINMENU));//A 
  3. ... 
  4. ... 
  5. case WM_EXITMENULOOP: 
  6.     { 
  7.         ...//C 
  8.     } 
  9.     break
  10. case WM_LBUTTONUP: 
  11.     { 
  12.         ... 
  13.         ::TrackPopupMenu(hDropFileMenu, TPM_RIGHTBUTTON, 
  14. ptl.x, ptl.y, 0, m_hWnd, NULL);//B 
  15.         ... 
  16.     } 
  17.     break
  18. case WM_COMMAND 
  19.     { 
  20.         // Command is not from menu. 
  21.         if (HIWORD(wParam) !=0 ) return;//D 
  22.         ... 
  23.     } 
  24. ... 
  25. ... 

 

  上面的代码片段是一个典型的菜单使用模式:A行先创建菜单,B行显示菜单,然后点击某个菜单项,执行到D行.不过怎么没有提到过C行呢?
  C行是在消息WM_EXITMENULOOP中处理的,它是释放菜单时其窗口收到的一个消息,关键问题是,这个消息上面时候发出?
  按照一般的逻辑思维,WM_EXITMENULOOP应该在WM_COMMAND之后,用户点击一个菜单项,发出WM_COMMAND消息,然后处理,最后释放菜单.若如此想的话就大错特错了,经过笔者测试发现,WM_EXITMENULOOP居然 在WM_COMMAND之前发生,也就是如果用户点击了某个菜单项,其窗口先收到的是WM_EXITMENULOOP,然后才收到WM_COMMAND,这就导致下面一个问题:
  当时笔者的程序有一个特点: 在菜单出现之前动态分配了一个内存(必须的,没有办法修改),然后在WM_LBUTTONUP时弹出一个菜单,下面有两个选择:
1)如果用户点击某个菜单项,窗口收到WM_COMMAND消息处理这个内存,之后,程序必须释放这个动态分配的内存;
2)如果用户不点击该菜单项,而且单击任意地方,菜单被释放,然后消失,程序也必须释放这个动态分配的内存;
这两个选择令人纠结的地方在于:
  无论哪个选择,窗口必然能够收到WM_EXITMENULOOP消息,但是我们不能在这个地方释放这块内存,否则,如果是第一个选择,那么可能程序崩溃(内存已经被释放);可是如果不在这个地方释放, 在哪里释放呢?如果在WM_COMMAND消息中释放,可用户可以做第2个选择,这样窗口收不到WM_COMMAND,则内存泄露,是不是很令人蛋疼?
  不过好在Window并未绝人之路,因为Windows为TrackPopupMenu提供了一个选项:TPM_RETURNCMD,这个选项会导致这个函数同步执行,它的返回值就是用户选择的命令ID,不过此时菜单的窗口就收不到WM_COMMAND了.
  事后仔细想想,windows将WM_EXITMENULOOP放在WM_COMMAND之前执行还是有道理的,因为程序在WM_COMMAND中很可能是一个同步操作,且时间比较长,这时如果还未执行WM_EXITMENULOOP,那么菜单将不会 被释放,也不会消失,这样的界面很不友好.另外,TrackPopupMenu函数也可以同步执行,因为调用这个函数的线程会阻塞在这个函数中,然后给用户显示一个菜单,此时,用户一般都户点击某个菜单项,函数返回,这并不会影响程序 的运行;即使用户不点击菜单项,而点击其它地方,该函数一样会返还,只是不会返回任何菜单项的命令,所有也不会影响程序的运行.有时候不得不佩服微软的人思虑周全.

 

 







本文转自jetyi51CTO博客,原文链接:http://blog.51cto.com/jetyi/640836 ,如需转载请自行联系原作者





相关文章
|
9天前
|
消息中间件 编译器 API
Windows窗口程序
Windows窗口程序
|
3月前
|
API Python Windows
python3应用windows api对后台程序窗口及桌面截图并保存的方法
python3应用windows api对后台程序窗口及桌面截图并保存的方法
89 1
|
4月前
|
Windows
(查看,和保存)windows下通过cmd命令符窗口查看、保存文件目录结构
(查看,和保存)windows下通过cmd命令符窗口查看、保存文件目录结构
59 0
|
7月前
|
存储 固态存储 Windows
在 Windows 中,当一个应用程序窗口被关闭,该应用程序将会保留在哪里?
在 Windows 中,当一个应用程序窗口被关闭,该应用程序将会保留在哪里?
89 0
|
8月前
|
API C++ Windows
Windows入门篇一之MSDN手册的使用和第一个窗口程序
Windows入门篇一之MSDN手册的使用和第一个窗口程序
Windows入门篇一之MSDN手册的使用和第一个窗口程序
|
8月前
|
Windows
Windows DOS窗口查看历史执行过的命令的三种方式
Windows DOS窗口查看历史执行过的命令的三种方式
|
10月前
|
Windows
WGCLOUD日常使用 - windows启动server,dos窗口显示乱码的问题处理
首先,这个乱码没有影响,忽略即可 这个是windows窗口编码导致的,不会影响程序运行,server/log下日志文件没有出现乱码,我们主要看日志文件
WGCLOUD日常使用 - windows启动server,dos窗口显示乱码的问题处理
|
10月前
|
数据可视化 Windows
Windows编程资源,菜单资源,图标资源,光标资源,上下文菜单,字符串资源,加速键资源(下)
Windows编程资源,菜单资源,图标资源,光标资源,上下文菜单,字符串资源,加速键资源(下)
|
10月前
|
数据可视化 编译器 Windows
Windows编程资源,菜单资源,图标资源,光标资源,上下文菜单,字符串资源,加速键资源(上)
Windows编程资源,菜单资源,图标资源,光标资源,上下文菜单,字符串资源,加速键资源
|
10月前
|
Windows
Windows编程基础,第一个Windows程序,注册窗口,创建窗口(下)
Windows编程基础,第一个Windows程序,注册窗口,创建窗口