分享
 
 
 

菜单枚举记

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

菜单枚举记

有一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 fType; //菜单格式类型

UINT fState;// 菜单状态:Enabled、Disabled or Grayed

UINT wID; //命令标识符

HMENU hSubMenu; //子菜单句柄,若无子菜单则为NULL

HBITMAP hbmpChecked; //根据这两个域值,可以自定义菜单项被选定时的标记,

HBITMAP hbmpUnchecked; //而不一定要是’√’或空白

DWORD dwItemData;//由English翻译为:应用程序定义的与菜单项相关的值(我也不明白)

LPTSTR dwTypeData; //菜单资源内容指针,指向String or BitMap or SEPARATOR资源

UINT cch; //若菜单项为MFT_STRING类型,则此项为dwTypeData长度

HBITMAP hbmpItem;//在调试程序时发现有此一项

} MENUITEMINFO, FAR *LPMENUITEMINFO;

参考资料: MSDN98(MicroSoft) MS SDK Help Files\Win32 Developer’s References(Inprise/Borland)

(附录1为上述API在PB中的Declare文本)

与Menu操作相关的Windows API Functions还比较多,可适度参考,动态库:USER32.DLL。

4、 其它:

a、.我在PB7中调用这些Windows功能,但在调试至GetMenuItemInfo时,单步运行却停滞不前,约

30小时后,我进行了如下操作:

a1、打开一Dos窗口,运行TDump c:\windows\system\user32.dll>user32.txt(Tdump.exe为Inprise公司的应用程序)

a2、回到Windows中,以记事本打开user32.txt,发现其中并无GetMenuItemInfo,但有GetMenuItemInfoA,若在VB中调用过WIN API,则可猜测此为何物。

a3、将GetMenuItemInfo改写(或Alias)成GetMenuItemInfoA,便OK 了!

b、菜单项命令标识符作用

在调用GetMenuItemInfoA之后,其值保存在MENUITEMINFO::wID中。

设现在获得一菜单项信息存储于MENUITEMINFO型结构体mii中,其部分内容为:

mii.cbsize=48

mii.dwTypeData=”打开文件”

mii.wID=10001

mii.fState=Enabled

mii.fType=MFT_STRING

对应函数引用标识

命令标识符wID

OpenFile()

10001

CloseFile()

10002

wID=10001

C、在上述GetMenuItemInfoA调用时,需对MENUITEMINFO的如下域赋值:

MENUITEMINFO::cbSize

MENUITEMINFO::fMask

MENUITEMINFO::dwTypeData

MENUITEMINFO:: cch

其中MENUITEMINFO::fMask可为如下常数值的组合(在相关资料中很难查到这些常数数值)

MIIM_STATE (= 1) MIIM_ID (= 2)

MIIM_SUBMENU (= 4) MIIM_CHECKMARKS (= 8)

MIIM_TYPE (=16) MIIM_DATA (=32)

附:

1、 相关API及结构体在PB中的Declare

Function Long GetMenu(long hWnd ) LIBRARY "USER32.DLL"

Function Long GetSubMenu(long hMenu,long nPos) LIBRARY "USER32.DLL"

Function Long GetMenuItemCount(long hMenu) LIBRARY "USER32.DLL"

Function Long EnableMenuItem(long hMenu,Ulong uIDEnableItem, Ulong uEnable)LIBRARY "USER32.DLL"

Function Long GetMenuItemInfoA(long hMenu, Ulong uItem, long fByPosition,ref MENUITEMINFO mii)LIBRARY "USER32.DLL"

Function Long DrawMenuBar(long hwnd) LIBRARY "USER32.DLL"

global type menuiteminfo from structure

unsignedlong cbsize

unsignedlong fmask

unsignedlong ftype

unsignedlong fstate

unsignedlong wid

long hsubmenu

long hbmpchecked

long hbmpunchecked

long dwitemdata

string dwtypedata

unsignedlong cch

long hbmpitem

end type

2、PB代码,根据需要,不同于C++代码(节选,有修改)

Public Function Int EnumMenuEndItems (long hwnd,int ins_upd)

long hm

constant int ins=0

if hwnd=0 or isnull(hwnd) then return 0

hm=GetMenu(handle(wmdi))

if ins_upd=ins then

delete from sec_fun using trans;

IF TRANS.SQLCODE=-1 THEN goto error

end if

if ismenu(hm)=0 then return -1

if fun(hm,ins_upd) =-1 then goto error

IF TRANS.SQLCODE=-1 THEN goto error

COMMIT USING TRANS;

delete from sec_auth where id_fun not in (select id_fun from sec_fun) using trans;//对

if trans.sqlcode=-1 and ins_upd=ins then messagebox("","某些操作可能不再存在,但用户仍然拥有该项操作权限,请手动删除!")

return 0

error:

ROLLBACK USING TRANS;

RETURN –1

End Fuction

Private Function Int FindMenuItem (HMENU hmenu,int ins_upd )

//ins=0

//upd=1

int i,c

long hm,res

menuiteminfo mii

mii.cbsize=48

mii.fmask=54

MII.FTYPE=0

c=getmenuitemcount(hmenu)

for i=0 to c -1

mii.dwtypedata=" "

mii.cch=63

if not isvalid(mii) then return -1

res=GetMenuItemInfoA(hmenu,i,255,mii)

if res=0 then continue

IF MII.HSUBMENU=0 THEN

IF NOT ISNULL(MII.DWTYPEDATA) THEN

choose case ins_upd

case 0

insert into sec_fun(id_fun,des_fun,HANDLE) values (:mii.wid,:mii.dwTypeData,:hmenu) USING TRANS;//保存’纯’菜单项的信息

IF TRANS.SQLCODE=-1 THEN return -1

case 1

update sec_fun set HANDLE=:hmenu where id_fun=:mii.wid USING TRANS;

IF TRANS.SQLCODE=-1 THEN return -2

end choose

ELSE

CONTINUE

END IF

ELSE

res= FindMenuItem (MII.HSUBMENU,ins_upd)

if res<>0 then return res

END IF

NEXT

return 0

End Function

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有