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 ...
随机推荐
- nginx的pass_proxy遇到的坑
Pass_proxy走内网,被请求方的php使用remote_addr得到就是转发机器的内网地址,如192.168.10.141这样的.走外网,被请求方php的remote_addr得到就是转发机器的 ...
- 【背景建模】PbModel
PbModel是基于概率模型的背景差分算法,其基本思想是像素点会因光照变化.运动物体经过产生多种颜色值,但是一段时间内,像素点处于静止状态的时间会比处于运动状态的时间长.因而一段时间内,像素点某个颜色 ...
- 完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群
完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群 maven依赖 <dependency> <groupId>org.quartz-scheduler ...
- 熟悉scss
//html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...
- asp.net保存网上图片到服务器
本文讲述的是根据一个图片的url地址,保存图片到asp.net服务器端的实现方法. 可以先了解这篇文章http://keleyi.com/a/bjac/0899dpgi.htm,以更好的理解本文. 首 ...
- 常用的css命名规则
头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wrapper 左右中:left rig ...
- [deviceone开发]-do_Viewshower的动画效果示例
一.简介 do_Viewshower组件也支持View之间的过场动画,支持大概12种,这个示例随机的切换12种动画中的一种,而且每次切换的动画时间不一样.直观的展示12种动画的效果.适合初学者. 二. ...
- [deviceone开发]-动画示例源码
一.简介 do_FrameAnimtionView组件是用加载GIF动态图片和加载一系列图片形成动画效果的展示组件,这个示例直观的展示组件基本的使用方式.适合初学者. 二.效果图 三.相关讨论 htt ...
- Ubuntu开机黑屏,无法进入系统
今天早上起来开机发现Ubuntu进不去了,启动项选择之后长时间的black of screen,击键盘.点鼠标毫无反应,后来实在等不下去了就按了一下电源键,以平时的性格就是强制关机的,这次轻轻碰一下就 ...
- 为什么你找不到优秀的GISer?
每年的三四月是招聘的黄金时节,故有金三银四的说法.求贤纳才对于处在发展上升期的公司来说,是全年性的常态化工作.只是这俩月市场上求职者数量较别的月份多.基数大了,淘到金子的概率自然会增加.大部分公司的伯 ...