菜单枚举记
有一MDI使用程序,现假设要枚举出其能够得到系统命令呼应所有菜单项的内容:如命令ID,资源名称,所在(子)菜单的句柄等,并对之进行操作。本文对此略述一二,未达意处,望各位海涵之外,以我之深度,唯与诸位共勉而已。
1、 我的迷惑
这几天修炼English Help,悟得些许正果,希望得与世人共超,尚不知能否无效,但为之而已。言归正传:
菜单项可以是菜单,反之亦然,此时菜单被称为子菜单;如果菜单项不是菜单,则它便是’纯菜单项’。以前我以为菜单中每一项都是菜单,我的思维中因此不再有菜单项的定义。可能这是个菜鸟级问题,但也可能您尚不甚解,那您不妨纸上谈兵一番,将最简单的菜单画上一画,再揣摩揣摩。
2、 菜单枚举算法
A、 菜单笼统结构之一(树型笼统):
如今要访问到这棵’树’的所有叶结点并处理之,方法如B所述。
B、 枚举算法(深度遍历,C++语法)
1. )求得当前结点的子结点数c;
2. )循环查询当前结点的I (0<=I<c)子结点信息:
若该子结点I无下级子结点,则子结点I为叶结点,按需处理后,作I=I+1,反复此步骤;
否则子结点I为分枝结点,置下级子结点为当前结点,转向1;
3.)遍历完毕。
int FindMenuItem(HMENU hmenu)//参数hmenu为分支结点资源标识
{
int i,c;
long res;
char* s=new char[33];
MENUITEMINFO mii;
mii.cbSize=sizeof(MENUITEMINFO);
mii.fMask=MIIM_DATA|MIIM_ID|MIIM_SUBMENU|MIIM_TYPE|MIIM_STATE|MIIM_CHECKMARKS;
mii.dwTypeData=s;
c=GetMenuItemCount(hmenu);//获取当前菜单所有的菜单项数目
for(i=0;i<c;i++)
{
mii.cch=32;//留意哦!
res=GetMenuItemInfo(hmenu,i,true,&mii);
if (res==0 ) {delete s;return -1;} //如果获取菜单信息失败
if (mii.hSubMenu==NULL)//
{
//若该菜单项非子菜单,则在此作相应处理
}
else
{
//若该菜单项为子菜单,则如此处理
res=FindMenuItem(mii.hSubMenu);//直接递归调用
if(res==-1){delete s;return -1;}
}
}
delete s;
return 0;
}
int EnumMenuEndItems(HWND hwnd)//开始遍历窗口菜单项。参数hwnd为菜单所在的窗体。
{
HMENU hmenu=GetMenu(hwnd);
if(hmenu==NULL) return –1;
return FindMenuItem(hmenu);
}
注: 此处代码仅仅描述算法。若使用到它处,依据不同的需求,Function的前往值和结点处理代码理所当然要发生改变。
附录2为上述代码的PB文本,两者略有不同,以资参考。
下面对上述代码中用到的Windows api 及 struct稍作解说。
3、 在的所用开发工具中Declare 如下Windows API及相关Struct (标准格式):
HMENU GetMenu( HWND hWnd);//前往值:hWnd所关联的窗口的菜单句柄
HMENU GetSubMenu(HMENU hMenu,int nPos);//前往值:hMenu所关联的菜单中第nPos项的子菜单句柄
int GetMenuItemCount(HMENU hMenu ); //前往值:hMenu所关联的菜单中的菜单项数目
BOOL WINAPI GetMenuItemInfo (
HMENU hMenu,
UINT uItem,
BOOL fByPosition, //该参数确定uItem为当前菜单项的命令标识还是在所属菜单中的排序位置号
LPMENUITEMINFO lpmii);
BOOL DrawMenuBar(HWND hWnd ); //重绘hWnd所关联的窗口的菜单
typedef struct tagMENUITEMINFO {
UINT cbSize; //本结构体物理大小,以byte为单位,其值实际上为48
UINT fMask; //确定想要查询或设置菜单项的哪能些内容
UINT