菜单枚举记

菜单枚举记

有一 MDI 应用程序,现假设要枚举出其能够得到系统命令响应所有菜单项的内容:如命令 ID ,资源名称,所在 ( 子 ) 菜单的句柄等,并对之进行操作。本文对此略述一二,未达意处,望各位海涵之外,以我之深度,唯与诸位共勉而已。

1、 我的迷惑

这几天修炼 English Help ,悟得些许正果,希望得与世人共超,尚不知是否有效,但为之而已。言归正传:

菜单项可以是菜单,反之亦然,此时菜单被称为子菜单;如果菜单项不是菜单,则它便是 ’ 纯菜单项 ’ 。以前我以为菜单中每一项都是菜单,我的思维中因此不再有菜单项的定义。可能这是个菜鸟级问题,但也可能您尚不甚解,那您不妨纸上谈兵一番,将最简单的菜单画上一画,再 琢磨琢磨。

2、 菜单 枚举算法

A、 菜单抽象结构之一(树型抽象):

现在要访问到这棵 ’ 树 ’ 的所有叶结点并处理之,方法如 B 所述。

B、 枚举算法 ( 深度遍历, C++ 语法 )

1. ) 求得当前结点的子结点数 c ;

2. ) 循环查询当前结点的 I (0<=I

  1<c) !="" (="" (mii.hsubmenu="NULL)//" (res="0" )="" );="" **="" *lpmenuiteminfo;="" ,="" -1;}="" .="" 0;="" 1="" 2="" 3="" 30="" 3、="" 48="" 4、="" 98(microsoft)="" ;="" _="" a="" a1="" api="" bitmap="" bool="" borland)="" byte="" c="GetMenuItemCount(hmenu);//" c:\windows\system\user32.dll="" cbsize;="" cch;="" char*="" char[33];="" declare="" delete="" developer’s="" disabled="" dos="" drawmenubar(hwnd="" dwitemdata;="" dword="" dwtypedata="" dwtypedata;="" else="" enabled="" english="" enummenuenditems(hwnd="" far="" fbyposition,="" files\win32="" findmenuitem(hmenu="" findmenuitem(hmenu);="" fmask;="" for(i="0;i&lt;c;i++)" fstate;="" ftype;="" function="" functions="" getmenu(="" getmenuitemcount(hmenu="" getmenuiteminfo="" getsubmenu(hmenu="" grayed="" hbitmap="" hbmpchecked;="" hbmpitem;="" hbmpunchecked;="" help="" hmenu="" hmenu)="" hmenu,="" hmenu,int="" hsubmenu;="" hwnd="" hwnd)="" hwnd);="" i="" i,c;="" if="" if(hmenu="NULL)" if(res="-1){delete" int="" long="" lpmenuiteminfo="" lpmii);="" lptstr="" menu="" menuiteminfo="" menuiteminfo,="" mft_string="" mii.cbsize="sizeof(MENUITEMINFO);" mii.cch="32" mii.dwtypedata="s;" mii.fmask="MIIM_DATA|MIIM_ID|MIIM_SUBMENU|MIIM_TYPE|MIIM_STATE|MIIM_CHECKMARKS;" mii;="" ms="" msdn="" npos="" npos);="" null="" or="" pb="" pb7="" references(inprise="" res="**FindMenuItem(mii.hSubMenu)**" res;="" return="" s="new" s;="" s;return="" sdk="" separator="" string="" struct="" tagmenuiteminfo="" tdump="" typedef="" uint="" uitem="" uitem,="" user32.dll="" wid;="" winapi="" windows="" {="" {delete="" }="" –1;="" ’="" √="" 、="" 、打开一="" 。="" 下面对上述代码中用到的="" 与="" 中的="" 中调用这些="" 为上述="" 为上述代码的="" 为分支结点资源标识="" 为分枝结点,置下级子结点为当前结点,转向="" 为单位,其值实际上为="" 为叶结点,按需处理后,作="" 为当前菜单项的命令标识还是在所属菜单中的排序位置号="" 为菜单所在的窗体。="" 其它:="" 则此项为="" 功能,但在调试至="" 动态库:="" 参数="" 参考资料:="" 及="" 及相关="" 否则子结点="" 命令标识符="" 在="" 在的所用开发工具中="" 在调试程序时发现有此一项="" 如下="" 如果获取菜单信息失败="" 子结点信息:="" 子菜单句柄,若无子菜单则为="" 小时后,我进行了如下操作:="" 开始遍历窗口菜单项。参数="" 我也不明白="" 我在="" 或空白="" 所关联的窗口的菜单="" 所关联的窗口的菜单句柄="" 所关联的菜单中的菜单项数目="" 所关联的菜单中第="" 操作相关的="" 文本="" 文本,两者略有不同,以资参考。="" 无下级子结点,则子结点="" 时,单步运行却停滞不前,约="" 本结构体物理大小,以="" 标准格式="" 根据这两个域值,可以自定义菜单项被选定时的标记,="" 此处代码仅仅描述算法。若应用到它处,根据不同的需要,="" 注意哦="" 注:="" 由="" 的返回值和结点处理代码理所当然要发生改变。="" 直接递归调用="" 确定想要查询或设置菜单项的哪能些内容="" 稍作解说。="" 窗口="" 类型="" 翻译为:应用程序定义的与菜单项相关的值="" 而不一定要是="" 若菜单项为="" 若该子结点="" 若该菜单项为子菜单,则如此处理="" 若该菜单项非子菜单,则在此作相应处理="" 获取当前菜单所有的菜单项数目="" 菜单格式类型="" 菜单状态:="" 菜单资源内容指针,指向="" 该参数确定="" 资源="" 运行="" 返回值:="" 还比较多,可适度参考="" 遍历完毕。="" 重绘="" 长度="" 附录="" 项的子菜单句柄="" ,重复此步骤;="" .="" :="" ;="">user32.txt  (  Tdump.exe  为  Inprise  公司的应用程序) 
  2
  3a2  、回到  Windows  中,以记事本打开  user32.txt  ,发现其中并无  GetMenuItemInfo  ,但有  GetMenuItemInfoA  ,若在  VB  中调用过  WIN API  ,则可猜测此为何物。 
  4
  5a3  、将  GetMenuItemInfo  改写  (  或  Alias)  成  GetMenuItemInfoA  ,便  OK  了  ! 
  6
  7b  、菜单项命令标识符作用 
  8
  9在调用  GetMenuItemInfoA  之后,其值保存在  MENUITEMINFO::wID  中。 
 10
 11设现在获得一菜单项信息存储于  MENUITEMINFO  型结构体  mii  中,其部分内容为: 
 12
 13mii.cbsize=48 
 14
 15mii.dwTypeData=”  打开文件  ” 
 16
 17mii.wID=10001 
 18
 19mii.fState=Enabled 
 20
 21mii.fType=MFT_STRING 
 22
 23对应函数引用标识 
 24
 25| 
 26
 27命令标识符  wID   
 28  
 29---|---  
 30  
 31OpenFile() 
 32
 33| 
 34
 3510001   
 36  
 37CloseFile() 
 38
 39| 
 40
 4110002   
 42  
 43wID=10001   
 44  
 45---  
 46  
 47  
 48
 49
 50C  、在上述  GetMenuItemInfoA  调用时,需对  MENUITEMINFO  的如下域赋值: 
 51
 52MENUITEMINFO::cbSize 
 53
 54MENUITEMINFO::fMask 
 55
 56MENUITEMINFO::dwTypeData 
 57
 58MENUITEMINFO:: cch 
 59
 60其中  MENUITEMINFO::fMask  可为如下常数值的组合  (  在相关资料中很难查到这些常数数值  ) 
 61
 62MIIM_STATE  (= 1)  MIIM_ID  (= 2) 
 63
 64MIIM_SUBMENU (= 4)  MIIM_CHECKMARKS  (= 8) 
 65
 66MIIM_TYPE  (=16)  MIIM_DATA  (=32) 
 67
 68附: 
 69
 701、  相关  API  及结构体在  PB  中的  Declare 
 71
 72Function Long GetMenu(long hWnd  ) LIBRARY "USER32.DLL" 
 73
 74Function Long GetSubMenu(long hMenu,long nPos) LIBRARY "USER32.DLL" 
 75
 76Function Long GetMenuItemCount(long hMenu) LIBRARY "USER32.DLL" 
 77
 78Function Long EnableMenuItem(long hMenu,Ulong uIDEnableItem, Ulong uEnable)LIBRARY "USER32.DLL" 
 79
 80Function Long GetMenuItemInfoA(long hMenu, Ulong uItem, long fByPosition,ref MENUITEMINFO mii)LIBRARY "USER32.DLL" 
 81
 82Function Long DrawMenuBar(long hwnd) LIBRARY "USER32.DLL" 
 83
 84global type menuiteminfo from structure 
 85
 86unsignedlong  cbsize 
 87
 88unsignedlong  fmask 
 89
 90unsignedlong  ftype 
 91
 92unsignedlong  fstate 
 93
 94unsignedlong  wid 
 95
 96long  hsubmenu 
 97
 98long  hbmpchecked 
 99
100long  hbmpunchecked 
101
102long  dwitemdata 
103
104string  dwtypedata 
105
106unsignedlong  cch 
107
108long  hbmpitem 
109
110end type 
111
1122  、  PB  代码,根据需要,不同于  C++  代码  (  节选,有修改  ) 
113
114Public Function Int EnumMenuEndItems (long hwnd,int ins_upd) 
115
116long hm 
117
118constant int ins=0 
119
120if hwnd=0 or isnull(hwnd) then return 0 
121
122hm=GetMenu(handle(wmdi)) 
123
124if ins_upd=ins then 
125
126delete from sec_fun using trans; 
127
128IF TRANS.SQLCODE=-1 THEN goto error 
129
130end if 
131
132if ismenu(hm)=0 then return -1 
133
134if fun(hm,ins_upd)  =-1 then goto error 
135
136IF TRANS.SQLCODE=-1 THEN goto error 
137
138COMMIT USING TRANS; 
139
140delete from sec_auth where id_fun not in (select id_fun from sec_fun) using trans;//  对 
141
142if trans.sqlcode=-1 and ins_upd=ins then messagebox("","  某些操作可能不再存在,但用户仍然拥有该项操作权限,请手动删除!  ") 
143
144return 0 
145
146error: 
147
148ROLLBACK USING TRANS; 
149
150RETURN –1 
151
152End Fuction 
153
154Private Function Int FindMenuItem (HMENU hmenu,int ins_upd ) 
155
156//ins=0 
157
158//upd=1 
159
160int i,c 
161
162long hm,res 
163
164menuiteminfo mii 
165
166mii.cbsize=48 
167
168mii.fmask=54 
169
170MII.FTYPE=0 
171
172c=getmenuitemcount(hmenu) 
173
174for i=0 to c -1 
175
176mii.dwtypedata="  " 
177
178mii.cch=63 
179
180if not isvalid(mii) then return -1 
181
182res=GetMenuItemInfoA(hmenu,i,255,mii) 
183
184if res=0 then continue 
185
186IF MII.HSUBMENU=0 THEN 
187
188IF NOT ISNULL(MII.DWTYPEDATA) THEN 
189
190choose case ins_upd 
191
192case 0 
193
194insert into sec_fun(id_fun,des_fun,HANDLE) values (:mii.wid,:mii.dwTypeData,:hmenu) USING TRANS;//  保存  ’  ** 纯  ** ’  菜单项的信息 
195
196IF TRANS.SQLCODE=-1 THEN return -1 
197
198case 1 
199
200update sec_fun set HANDLE=:hmenu where id_fun=:mii.wid USING TRANS; 
201
202IF TRANS.SQLCODE=-1 THEN return -2 
203
204end choose 
205
206ELSE 
207
208CONTINUE 
209
210END IF 
211
212ELSE 
213
214res= FindMenuItem (MII.HSUBMENU,ins_upd) 
215
216if res&lt;&gt;0 then return res 
217
218END IF 
219
220NEXT 
221
222return 0 
223
224End Function</c)>
Published At
Categories with 数据库类
Tagged with
comments powered by Disqus