WIN 下的超动态菜单(一)简介

WIN 下的超动态菜单(二)用法

WIN 下的超动态菜单(三)代码

作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/

        auto_dynamenu 是一个动态生成WINDOWS菜单的c++封装库,设计思路是要尽量简化动态菜单的生成代码,在程序界面任何地方想要显示菜单(特别是右键菜单)的时候,可以方便生成菜单,特别可以根据程序当时的内部数据,内部状态来生成不同的动态菜单。

        auto_dynamenu 只封装了一个静态的接口函数,这样处理的目的是把类的实现代码可以放在头文件的类的声明里面,这样使用的时候只要包含头文件就可以直接调用了,不需要把实现文件加入工程,简化操作。

类的接口函数定义

  1. /**************************************************************************************************\
  2. * static int : 返回值,表明选择了哪个菜单项或者被更新的 nDefaultValue
  3. * dynamenu :
  4. * HWND hWnd : 当前窗口句柄
  5. * LPPOINT pPoint : 显示菜单的位置,通常为0即可,自动确定显示的菜单位置
  6. * char* pszMenu : 表明动态菜单内容的菜单字符串
  7. * int nDefaultMode : 自动更新菜单选择标记的模式,0 无,1 等于模式,2 位模式
  8. * int nDefaultValue : 缺省值,根据这个值,按照 nDefaultMode 来显示菜单项的选择标记
  9. \**************************************************************************************************/
  10. class auto_dynamenu
  1. {
  1. public:
  1. static int dynamenu(HWND hWnd, LPPOINT pPoint, char* pszMenu, int nDefaultMode, int nDefaultValue);
  1. };

参数:pszMenu

        接口用一个格式化的字符串 pszMenu 来表示动态菜单,具体格式规则如下:

(1)每个菜单项为一个以 \n 结束的字符串

(2)菜单项的字符串通常以等号 = 分割为两部分,等号前面为要显示的菜单内容,等号后面为选择这个菜单后的取值

(3)菜单项的字符串里面如果没有等号,表明选择菜单返回的时候,返回的是菜单项字符串

(3)每个菜单项字符串前面可以加如下的修饰符:

[a] *(星号):表示这个菜单项前面有点的选择标记

[b] ^:表示这个菜单项前面有对勾的选择标记

[c] #:表示这个菜单项是灰色的

[d] -(减号):表明这个菜单项和下一个菜单项之间分为不同的列(多列的菜单)

[e] `(键盘左上角的按键):表示一个没有意义的占位符

[f] ~:表明是一个菜单分割线

(4)可以用单独一行的 ~ 表示一个菜单分割横线,“~\n”

(5)菜单项字符串等号前面部分的竖线字符”|“ 把菜单分割为父菜单和子菜单

(6)把不同的菜单项的字符串连接为一个完整的字符串就可以描述这个整个菜单了

例如:

  1. char szMenu[] =
  2. "选项1=20\n" //选项1对应数值20,选择这个函数返回20
  3. "选项2=0x20\n" //选择2对应数值0x20,选择这个函数返回0x20
  4. "选项3=0\n" //选项3对应数值0,选择这个函数返回 INT_MAX(因为函数返回0代表没有选择菜单项,所以0用INT_MAX返回值表示)
  5. "~\n" //这个代表一个菜单分割横线
  6. "录像|通用格式|avi格式=-1\n" //多级子菜单,选择这个返回-1
  7. "录像|通用格式|~\n" //多级子菜单内部的分割横线
  8. "录像|通用格式|mkv格式=-2\n" //多级子菜单,选择这个返回-2
  9. "录像|~\n"
  10. "录像|专用格式|rdv格式=-3\n" //多级子菜单,选择这个返回-3
  11. "~\n"
  12. "#暂停处理\n" //灰色禁用的菜单项,无法选择,可以用于显示信息
  13. "~\n"
  14. "控制|^开始视频=10\n" //显示选中的视频开始菜单,选择返回10
  15. "控制|结束视频=11\n" //显示没有选中的菜单,选择返回11
  16. "播放当前录像 1.avi=d:\\1.avi\n" //返回文件名字符串指针
  17. ;

上面的示例菜单字符串显示出来的菜单如下:

参数:hWnd

        虽然菜单的消息不发往任何窗口,但是这个必须指定一个有效的窗口句柄,否则菜单显示不出来。通常指定对鼠标右键响应要显示菜单的窗口,或者主窗口。

参数:pPoint

        菜单显示位置坐标POINT的指针,用于指定菜单的显示位置,是屏幕坐标。通常可以给0,这时程序自动选择菜单的显示位置,通常根据鼠标当前位置的控件类型确定,具体如下:

(1)如果是 BUTTON,工具栏上的按钮,则显示在这个控件的下方,左侧对齐

(2)如果是TreeView,ListView则显示在当前鼠标位置的条目的下方

(3)如果是TabCtrl则显示在鼠标当前的Tab页的页头的下方

(4)大小像个按钮的ActiveX控件,显示在下方

(5)其他显示在鼠标的当前位置

参数pPoint备注

         在这个参数给0的时候,代码自动确定菜单显示位置,但由于作者通常在VC6下编程(参见博文《我是如何把VC6一直用到2016年的》),因此代码中判断控件类型用的 ClassName 没有包含新版 Visual C 带的控件的类,可能需要使用者增加一些代码中的控件类名,对不同的控件确定不同的显示菜单的位置。具体情况参考文档《WIN 下超动态菜单(三)代码》。

参数:nDefaultMode

        缺省模式,如果为0,没有缺省模式,菜单项的标记都在菜单字符串中指定。

        如果为1,相等模式,如果某个菜单项的取值等于传入的nDefaultValue则显示选中标记。

        如果为2,为与模式,如果某个菜单项的取值与nDefaultValue的位与不为0,则显示选中标记。

参数:nDefaultValue

        当前的缺省值,配合nDefaultValue使用。

返回值:

        程序应该根据返回值来判断选择了哪个菜单,根据nDefaultMode不同含义有差别,用法也有差异。

(1)如果nDefaultMode为0

(a)返回值为0的时候,表明没有选择任何菜单选项;

(b)返回值为INT_MAX,表明选择了某个值为0的菜单项;

(c)如果选择的菜单项字符串里面有等号,并且等号后面是数字(支持十进制和十六进制写法),则返回这个数字;

(d)如果选择的菜单项字符串里面的等号后面是字符串,则返回这个等号后面的字符串的指针;

(e)如果选择的菜单项字符串里面没有等号,则返回这个菜单项的字符串的指针。

(2)如果 nDefaultMode 为 1 或者 2

        则返回nDefaultValue经过修改后的值,如果没有选择任何菜单,返回值等于nDefaultValue。

直接可以这样写 :

  1. nDefaultValue = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, pszMenu, nDefaultMode/*1 or 2*/, nDefaultValue);

动态菜单显示及根据返回值进行处理示例

  1. char szMenu[] =
  2. "选项1=20\n" //选项1对应数值20,选择这个函数返回20
  3. "选项2=0x20\n" //选择2对应数值0x20,选择这个函数返回20
  4. "选项3=0\n" //选项3对应数值0,选择这个函数范围 INT_MAX(因为函数返回0代表没有选择菜单项,所以0用INT_MAX返回值表示)
  5. "~\n" //这个代表一个菜单分割横线
  6. "录像|通用格式|avi格式=-1\n" //多级子菜单,选择这个返回-1,可以为负值
  7. "录像|通用格式|~\n" //多级子菜单内部的分割横线
  8. "录像|通用格式|mkv格式=-2\n" //多级子菜单,选择这个返回-2
  9. "录像|~\n"
  10. "录像|专用格式|rdv格式=-3\n" //多级子菜单,选择这个返回-3
  11. "~\n"
  12. "#暂停处理\n" //灰色禁用的菜单项,无法选择,可以用于显示信息
  13. "~\n"
  14. "控制|^开始视频=10\n" //显示选中的视频开始菜单,选择返回10
  15. "控制|结束视频=11\n" //显示没有选中的菜单,选择返回11
  16. "播放当前录像 1.avi=d:\\1.avi\n" //返回文件名字符串指针
  17. ;
  18.  
  19. int index = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 0, 0);
  20. switch (index)
  21. {
  22. case 0:
  23. //菜单没有选择,不做任何处理
  24. break;
  25. case 20:
  26. //选项1
  27. break;
  28. case 0x20:
  29. //选项2
  30. break;
  31. case INT_MAX:
  32. //选项3,这个菜单项的值为0,通常可以避免这样的情况,就不需要处理这个特殊的值了
  33. break;
  34. case -1:
  35. //avi 录像
  36. break;
  37. case -2:
  38. //mkv录像
  39. break;
  40. case -3:
  41. //rdv录像
  42. break;
  43. case 10:
  44. //开始视频
  45. break;
  46. case 11:
  47. //停止视频
  48. break;
  49. default:
  50. {
  51. char * pfile = (char*)index;
  52. //选中了最后的文件菜单项,pfile为 “d:\\1.avi” 字符串的指针
  53. }
  54. break;
  55. }

两点注释:

        (1)上面的代码里面的菜单项的选中标记,都是在菜单字符串里面手工指定的,这时 nDefaultMode 和 nDefaultValue 指定为0。

        (2)上面代码中的菜单项是在源代码中硬编码的,实际使用的时候可以动态生成,根据程序的状态来组建菜单字符串,例如:

  1. char szMenu[1024] = {0};
  2.  
  3. int n = 0;
  4.  
  5. if (value == 2)
  6. n += sprintf(szMenu + n, "^");
  7.  
  8. n += sprintf(szMenu + n, "值2=2\n");
  9.  
  10. if (value == 4)
  11. n += sprintf(szMenu + n, "^");
  12.  
  13. n += sprintf(szMenu + n, "值4=4\n");

nDefaultMode=1时的示例

(1)模式1为相等模式 ( nDefaultMode = 1 ),当某个菜单项的数值等于输入的 nDefaultValue 的时候,这个菜单项前面有选中标记

  1. int val = 32; //nDefaultValue
  2.  
  3. char szMenu[] =
  4. "整数1=1\n"
  5. "整数20=20\n"
  6. "整数32=32\n"
  7. "整数0x99=0x99\n"
  8. ;
  9.  
  10. //注意上面的菜单字符串里面没有选中标记
  11.  
  12. //nDeaultMode = 1,当菜单项等于 nDefaultValue的时候显示选中标记
  13.  
  14. val = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 1, val);
  15.  
  16. //返回值为当前选中的菜单项对应的值,如果没有选择菜单,这个值保持原来的不变

nDefaultMode=2时的示例

        模式2为位模式 ( nDefaultMode = 2 ),当菜单项的数值所对应的位 与nDefaultValue位与的时候不为0,则菜单项前面显示选中标记。

  1. DWORD flags = 0x82; //当前的值 nDefaultValue
  2.  
  3. char szMenu[] =
  4. "标记1=1\n"
  5. "标记2=2\n"
  6. "标记3=4\n"
  7. "标记4=8\n"
  8. "标记5=0x10\n"
  9. "标记6=0x20\n"
  10. "标记7=0x40\n"
  11. "标记8=0x80\n"
  12. ;
  13. //上面的菜单字符串内没有选择标记,程序自动根据 nDefaultValue 把对应的位加上选中标记
  14. //nDefaultMode = 2
  15.  
  16. flags = (DWORD)auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 2, flags);
  1. //返回值就是flags,如果没有选择菜单项,那么这个值不变

下载

        可以在下面的链接下载代码和示例程序:

        http://files.cnblogs.com/files/tomview/dynamenu_20160524.rar

WIN 下的超动态菜单(二)用法的更多相关文章

  1. WIN 下的超动态菜单(三)代码

    WIN 下的超动态菜单(一)简介 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/ 超动态 ...

  2. WIN 下的超动态菜单(一)

    WIN 下的超动态菜单(一)介绍 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/     ...

  3. Bootstrap历练实例:导航内下拉菜单的用法

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  4. .net core3.1 abp动态菜单和动态权限(思路) (二)

    ps:本文需要先把abp的源码下载一份来下,跟着一起找实现,更容易懂 在abp中,对于权限和菜单使用静态来管理,菜单的加载是在登陆页面的地方(具体是怎么知道的,浏览器按F12,然后去sources中去 ...

  5. Win下最爱效率利器:AutoHotKey

    AutoHotkey是一个windows下的开源.免费.自动化软件工具.它由最初旨在提供键盘快捷键的脚本语言驱动(称为:热键),随着时间的推移演变成一个完整的脚本语言.但你不需要把它想得太深,你只需要 ...

  6. 动态创建二维vector数组 C和C++ 及指针与引用的区别

    二维vectorvector<vector <int> > ivec(m ,vector<int>(n));    //m*n的二维vector 动态创建m*n的二 ...

  7. 【vue】iView-admin2.0动态菜单路由

    vue项目实现动态路由有俩种方式 一.前端在routers中写好--所有--路由表 <前端控制路由>,登录时根据用户的角色权限来动态的显示菜单路由 二.前端通过调用接口请求拿到当前用户-- ...

  8. 转帖: 一份超全超详细的 ADB 用法大全

    增加一句 连接 网易mumu模拟器的方法 adb  connect 127.0.0.1:7555 一份超全超详细的 ADB 用法大全 2016年08月28日 10:49:41 阅读数:35890 原文 ...

  9. Delphi编程中动态菜单要点归纳

      一.创建菜单并添加项目 在设计程序时,有时需要动态创建菜单, 通常使用以下的语句: PopupMenu1 := TPopupMenu.Create(Self);  Item := TMenuIte ...

随机推荐

  1. 《Java4android》视频学习笔记——面向对象的应用(一)

    ---恢复内容开始--- 有一台HP打印机需要一个程序来实现开机,打印,关机这三个功能 class HPprinter { void open(){ System.out.println(" ...

  2. [moka同学笔记]Yii2 数据操作Query Builder 2

    Query Builder $rows = (new \yii\db\Query()) ->select(['dyn_id', 'dyn_name']) ->from('zs_dynast ...

  3. mysql 5.7.17发布

    Mysql 5.7.17发布了,主要修复: Changes in MySQL 5.7.17 (2016-12-12, General Availability) Compilation Notes M ...

  4. iCheck.js

    一.iCheck:http://www.bootcss.com/p/icheck/ 1.选择一个颜色主题,网上有,有了一个肤色主题,然后就是把这个肤色主题的css文件复制到iCheck文件夹里面 2. ...

  5. QRCode.js 生成二维码

    QRCode.js 是一个用于生成二维码图片的插件. github地址 在线实例 实例预览 基础示例 实例预览 API 接口 使用方法 载入 JavaScript 文件 <script src= ...

  6. Ampersand.js - 模块化的 JS 应用程序开发框架

    Ampersand.js 是一个高度模块化,松耦合,用于构建先进的 JavaScript 应用程序的框架.通过良好定义的方法,结合了一系列微小的 CommonJS 模块.条理清晰,没有多余的冗余代码. ...

  7. 使用 HTML5 WebGL 实现逼真的云朵效果

    这里给大家展示一个使用 HTML5 WebGL 实现超逼真的云朵效果.WebGL 是一项在网页浏览器呈现3D画面的技术,有别于过去需要安装浏览器插件,通过 WebGL 的技术,只需要编写网页代码即可实 ...

  8. [SharePoint] SharePoint 错误集 1

    1. Delete a site collection · Run command : Remove-SPSite –Identity http://ent132.sharepoint.hp.com/ ...

  9. 腾讯bugly团队提供的android国内镜像

    腾讯bugly团队提供的国内镜像   如果使用Android SDK Manager下载比较慢或者打不开,可以使用国内镜像 使用说明 http://android-mirror.bugly.qq.co ...

  10. Android Handler机制(三)----Looper源码解析

    一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...