日期:2013-10-09  浏览次数:20493 次


菜单枚举记

 

有一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