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 ,如需转载请自行联系原作者





相关文章
|
7月前
|
消息中间件 编译器 API
Windows窗口程序
Windows窗口程序
|
3月前
|
Windows
windows 11 恢复右键传统菜单
windows 11 恢复右键传统菜单
207 27
|
2月前
|
API Windows
Windows之窗口原理
这篇文章主要介绍了Windows窗口原理和如何使用Windows API创建和管理窗口。
65 0
|
7月前
|
API Python Windows
python3应用windows api对后台程序窗口及桌面截图并保存的方法
python3应用windows api对后台程序窗口及桌面截图并保存的方法
549 1
|
6月前
|
Windows
windows系统vbs脚本 恶搞关不掉的窗口 以及解决办法
windows系统vbs脚本 恶搞关不掉的窗口 以及解决办法
141 2
|
6月前
|
Windows
逆向学习Windows篇:通过编写函数处理菜单消息
逆向学习Windows篇:通过编写函数处理菜单消息
42 0
|
6月前
|
C++ UED 开发者
逆向学习 MFC 篇:视图分割和在 C++ 的 Windows 窗口程序中添加图标的方法
逆向学习 MFC 篇:视图分割和在 C++ 的 Windows 窗口程序中添加图标的方法
94 0
|
7月前
|
Windows
(查看,和保存)windows下通过cmd命令符窗口查看、保存文件目录结构
(查看,和保存)windows下通过cmd命令符窗口查看、保存文件目录结构
252 0
WGCLOUD日常使用 - windows启动server,dos窗口显示乱码的问题处理
首先,这个乱码没有影响,忽略即可 这个是windows窗口编码导致的,不会影响程序运行,server/log下日志文件没有出现乱码,我们主要看日志文件
WGCLOUD日常使用 - windows启动server,dos窗口显示乱码的问题处理
|
API C++ Windows
Windows入门篇一之MSDN手册的使用和第一个窗口程序
Windows入门篇一之MSDN手册的使用和第一个窗口程序
Windows入门篇一之MSDN手册的使用和第一个窗口程序