WIN 下的超动态菜单(二)用法
WIN 下的超动态菜单(二)用法
作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/
auto_dynamenu 是一个动态生成WINDOWS菜单的c++封装库,设计思路是要尽量简化动态菜单的生成代码,在程序界面任何地方想要显示菜单(特别是右键菜单)的时候,可以方便生成菜单,特别可以根据程序当时的内部数据,内部状态来生成不同的动态菜单。
auto_dynamenu 只封装了一个静态的接口函数,这样处理的目的是把类的实现代码可以放在头文件的类的声明里面,这样使用的时候只要包含头文件就可以直接调用了,不需要把实现文件加入工程,简化操作。
类的接口函数定义
/**************************************************************************************************\
* static int : 返回值,表明选择了哪个菜单项或者被更新的 nDefaultValue
* dynamenu :
* HWND hWnd : 当前窗口句柄
* LPPOINT pPoint : 显示菜单的位置,通常为0即可,自动确定显示的菜单位置
* char* pszMenu : 表明动态菜单内容的菜单字符串
* int nDefaultMode : 自动更新菜单选择标记的模式,0 无,1 等于模式,2 位模式
* int nDefaultValue : 缺省值,根据这个值,按照 nDefaultMode 来显示菜单项的选择标记
\**************************************************************************************************/
class auto_dynamenu
{
public:
static int dynamenu(HWND hWnd, LPPOINT pPoint, char* pszMenu, int nDefaultMode, int nDefaultValue);
};
参数:pszMenu
接口用一个格式化的字符串 pszMenu 来表示动态菜单,具体格式规则如下:
(1)每个菜单项为一个以 \n 结束的字符串
(2)菜单项的字符串通常以等号 = 分割为两部分,等号前面为要显示的菜单内容,等号后面为选择这个菜单后的取值
(3)菜单项的字符串里面如果没有等号,表明选择菜单返回的时候,返回的是菜单项字符串
(3)每个菜单项字符串前面可以加如下的修饰符:
[a] *(星号):表示这个菜单项前面有点的选择标记
[b] ^:表示这个菜单项前面有对勾的选择标记
[c] #:表示这个菜单项是灰色的
[d] -(减号):表明这个菜单项和下一个菜单项之间分为不同的列(多列的菜单)
[e] `(键盘左上角的按键):表示一个没有意义的占位符
[f] ~:表明是一个菜单分割线
(4)可以用单独一行的 ~ 表示一个菜单分割横线,“~\n”
(5)菜单项字符串等号前面部分的竖线字符”|“ 把菜单分割为父菜单和子菜单
(6)把不同的菜单项的字符串连接为一个完整的字符串就可以描述这个整个菜单了
例如:
char szMenu[] =
"选项1=20\n" //选项1对应数值20,选择这个函数返回20
"选项2=0x20\n" //选择2对应数值0x20,选择这个函数返回0x20
"选项3=0\n" //选项3对应数值0,选择这个函数返回 INT_MAX(因为函数返回0代表没有选择菜单项,所以0用INT_MAX返回值表示)
"~\n" //这个代表一个菜单分割横线
"录像|通用格式|avi格式=-1\n" //多级子菜单,选择这个返回-1
"录像|通用格式|~\n" //多级子菜单内部的分割横线
"录像|通用格式|mkv格式=-2\n" //多级子菜单,选择这个返回-2
"录像|~\n"
"录像|专用格式|rdv格式=-3\n" //多级子菜单,选择这个返回-3
"~\n"
"#暂停处理\n" //灰色禁用的菜单项,无法选择,可以用于显示信息
"~\n"
"控制|^开始视频=10\n" //显示选中的视频开始菜单,选择返回10
"控制|结束视频=11\n" //显示没有选中的菜单,选择返回11
"播放当前录像 1.avi=d:\\1.avi\n" //返回文件名字符串指针
;
上面的示例菜单字符串显示出来的菜单如下:

参数: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。
直接可以这样写 :
nDefaultValue = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, pszMenu, nDefaultMode/*1 or 2*/, nDefaultValue);
动态菜单显示及根据返回值进行处理示例
char szMenu[] =
"选项1=20\n" //选项1对应数值20,选择这个函数返回20
"选项2=0x20\n" //选择2对应数值0x20,选择这个函数返回20
"选项3=0\n" //选项3对应数值0,选择这个函数范围 INT_MAX(因为函数返回0代表没有选择菜单项,所以0用INT_MAX返回值表示)
"~\n" //这个代表一个菜单分割横线
"录像|通用格式|avi格式=-1\n" //多级子菜单,选择这个返回-1,可以为负值
"录像|通用格式|~\n" //多级子菜单内部的分割横线
"录像|通用格式|mkv格式=-2\n" //多级子菜单,选择这个返回-2
"录像|~\n"
"录像|专用格式|rdv格式=-3\n" //多级子菜单,选择这个返回-3
"~\n"
"#暂停处理\n" //灰色禁用的菜单项,无法选择,可以用于显示信息
"~\n"
"控制|^开始视频=10\n" //显示选中的视频开始菜单,选择返回10
"控制|结束视频=11\n" //显示没有选中的菜单,选择返回11
"播放当前录像 1.avi=d:\\1.avi\n" //返回文件名字符串指针
; int index = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 0, 0);
switch (index)
{
case 0:
//菜单没有选择,不做任何处理
break;
case 20:
//选项1
break;
case 0x20:
//选项2
break;
case INT_MAX:
//选项3,这个菜单项的值为0,通常可以避免这样的情况,就不需要处理这个特殊的值了
break;
case -1:
//avi 录像
break;
case -2:
//mkv录像
break;
case -3:
//rdv录像
break;
case 10:
//开始视频
break;
case 11:
//停止视频
break;
default:
{
char * pfile = (char*)index;
//选中了最后的文件菜单项,pfile为 “d:\\1.avi” 字符串的指针
}
break;
}
两点注释:
(1)上面的代码里面的菜单项的选中标记,都是在菜单字符串里面手工指定的,这时 nDefaultMode 和 nDefaultValue 指定为0。
(2)上面代码中的菜单项是在源代码中硬编码的,实际使用的时候可以动态生成,根据程序的状态来组建菜单字符串,例如:
char szMenu[1024] = {0};
int n = 0;
if (value == 2)
n += sprintf(szMenu + n, "^");
n += sprintf(szMenu + n, "值2=2\n");
if (value == 4)
n += sprintf(szMenu + n, "^");
n += sprintf(szMenu + n, "值4=4\n");
nDefaultMode=1时的示例
(1)模式1为相等模式 ( nDefaultMode = 1 ),当某个菜单项的数值等于输入的 nDefaultValue 的时候,这个菜单项前面有选中标记

int val = 32; //nDefaultValue
char szMenu[] =
"整数1=1\n"
"整数20=20\n"
"整数32=32\n"
"整数0x99=0x99\n"
;
//注意上面的菜单字符串里面没有选中标记
//nDeaultMode = 1,当菜单项等于 nDefaultValue的时候显示选中标记
val = auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 1, val);
//返回值为当前选中的菜单项对应的值,如果没有选择菜单,这个值保持原来的不变
nDefaultMode=2时的示例
模式2为位模式 ( nDefaultMode = 2 ),当菜单项的数值所对应的位 与nDefaultValue位与的时候不为0,则菜单项前面显示选中标记。

DWORD flags = 0x82; //当前的值 nDefaultValue
char szMenu[] =
"标记1=1\n"
"标记2=2\n"
"标记3=4\n"
"标记4=8\n"
"标记5=0x10\n"
"标记6=0x20\n"
"标记7=0x40\n"
"标记8=0x80\n"
;
//上面的菜单字符串内没有选择标记,程序自动根据 nDefaultValue 把对应的位加上选中标记
//nDefaultMode = 2
flags = (DWORD)auto_dynamenu::dynamenu(GetSafeHwnd(), 0, szMenu, 2, flags);
//返回值就是flags,如果没有选择菜单项,那么这个值不变
下载
可以在下面的链接下载代码和示例程序:
http://files.cnblogs.com/files/tomview/dynamenu_20160524.rar
WIN 下的超动态菜单(二)用法的更多相关文章
- WIN 下的超动态菜单(三)代码
WIN 下的超动态菜单(一)简介 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/ 超动态 ...
- WIN 下的超动态菜单(一)
WIN 下的超动态菜单(一)介绍 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/ ...
- Bootstrap历练实例:导航内下拉菜单的用法
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- .net core3.1 abp动态菜单和动态权限(思路) (二)
ps:本文需要先把abp的源码下载一份来下,跟着一起找实现,更容易懂 在abp中,对于权限和菜单使用静态来管理,菜单的加载是在登陆页面的地方(具体是怎么知道的,浏览器按F12,然后去sources中去 ...
- Win下最爱效率利器:AutoHotKey
AutoHotkey是一个windows下的开源.免费.自动化软件工具.它由最初旨在提供键盘快捷键的脚本语言驱动(称为:热键),随着时间的推移演变成一个完整的脚本语言.但你不需要把它想得太深,你只需要 ...
- 动态创建二维vector数组 C和C++ 及指针与引用的区别
二维vectorvector<vector <int> > ivec(m ,vector<int>(n)); //m*n的二维vector 动态创建m*n的二 ...
- 【vue】iView-admin2.0动态菜单路由
vue项目实现动态路由有俩种方式 一.前端在routers中写好--所有--路由表 <前端控制路由>,登录时根据用户的角色权限来动态的显示菜单路由 二.前端通过调用接口请求拿到当前用户-- ...
- 转帖: 一份超全超详细的 ADB 用法大全
增加一句 连接 网易mumu模拟器的方法 adb connect 127.0.0.1:7555 一份超全超详细的 ADB 用法大全 2016年08月28日 10:49:41 阅读数:35890 原文 ...
- Delphi编程中动态菜单要点归纳
一.创建菜单并添加项目 在设计程序时,有时需要动态创建菜单, 通常使用以下的语句: PopupMenu1 := TPopupMenu.Create(Self); Item := TMenuIte ...
随机推荐
- GIT 查看/修改用户名和邮箱地址
用户名和邮箱地址的作用用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变.每次commit都会用用户名和邮箱纪录.github的contributions统计就是按邮箱来统计的.查看用户 ...
- 如何在MFC对话框应用程序中使用ColorPicker控件
在日常的应用程序开发中,当涉及到曲线绘制时,为了将多条不同类型的曲线区分开,常常需要将它们指定不同的颜色.今天在这里简单的记录一下,如何实现及使用ColorPicker控件.程序用到4个文件依次为:C ...
- android实现两个activity数据交互
android如何实现两个Activity数据交互?主要是根据Intent的携带功能,intent可以携带很多信息,比如Bundle,URI甚至对象(此时要序列化,并且对象里面的成员变量如果是对象,也 ...
- 提升手持设备点击速度之touch事件带来的坑!
前言 上周六,我将我们项目的click换成了tap事件,于是此事如梦魇一般折磨了我一星期!!! 经过我前仆后继的努力,不计代价的牺牲,不断的埋坑填坑,再埋坑的动作,最后悲伤的发现touch事件确实是个 ...
- JavaScript学习笔记-函数
函数的两种创建方式:函数定义表达式.函数声明语句 编译时,函数声明语句创建的函数会‘被提前’至外部函数的作用域顶部,在该作用域内可以被随意调用: 而函数表达式创建的函数,要调用它必须赋值给一个变量,编 ...
- HTML5移动开发学习笔记
最近做webapp项目过程中,发现坑还是挺多的,以下是网络收集一些开发中的常见问题及知识汇总,以便查阅,慢慢更新:). meta 基础知识 H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 < ...
- 将Win10变回Win7/WinXP界面
前往 Classic Shell 的网站(传送门:http://www.classicshell.net/)进行下载安装.第一次开启 时,程序会让你选择一款面板:第一个是 Windows 2000 的 ...
- linux集群运维工具:clustershell和pssh
由于需要安装hadoop集群,有10台机器需要安装,一开始打算用SCP复制,后来觉得不可接受(实际现场可能数倍的机器集群,就是10台也不想干).后来在网上找了,发现了clustershell和pssh ...
- [SharePoint] SharePoint 错误集 3
阅读目录 1. workflow 流程走不下去,报 workflow fails to run 的错误 2. 安装sharepoint prerequisit总是在web server (iis)这步 ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q9-Q12)
Question 9 You are designing an external binary large object (BLOB) store provider by implementing t ...