菜单枚举记 
有一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