選單列舉記 (轉)
選單列舉記
:namespace prefix = o ns = "urn:schemas--com::office" />
有一MDI應用,現假設要列舉出其能夠得到命令響應所有選單項的內容:如命令ID,資源名稱,所在(子)選單的控制程式碼等,並對之進行操作。本文對此略述一二,未達意處,望各位海涵之外,以我之深度,唯與諸位共勉而已。
1、 我的迷惑
這幾天修煉English Help,悟得些許正果,希望得與世人共超,尚不知是否有效,但為之而已。言歸正傳:
選單項可以是選單,反之亦然,此時選單被稱為子選單;如果選單項不是選單,則它便是’純選單項’。以前我以為選單中每一項都是選單,我的思維中因此不再有選單項的定義。可能這是個菜鳥級問題,但也可能您尚不甚解,那您不妨紙上談兵一番,將最簡單的選單畫上一畫,再琢磨琢磨。
2、 選單列舉演算法
A、 選單抽象結構之一(樹型抽象):
現在要訪問到這棵’樹’的所有葉結點並處理之,方法如B所述。
B、 列舉演算法(深度遍歷,C++語法)
1. )求得當前結點的子結點數c;
2. )迴圈查詢當前結點的I (0<=I 若該子結點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 { 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文字,兩者略有不同,以資參考。 下面對上述程式碼中用到的 及 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; //而不一定要是’√’或空白 D 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 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:windowssystemuser32.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 unableItem, 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.CODE=-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 ( 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
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-998631/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 列舉程式 (轉)
- 前臺呼叫下拉選單框值(列舉欄位)
- 列舉簡單總結
- Java列舉:為什麼它是單例模式的最佳選擇?Java單例模式
- c#列舉轉換C#
- 屬性列舉法(轉載)
- c++11 實現列舉值到列舉名的轉換C++
- 為什麼說列舉更佔記憶體,列舉原理是什麼?記憶體
- Java 列舉、JPA 和 PostgreSQL 列舉JavaSQL
- Java 利用列舉實現單例模式Java單例模式
- 簡單探討TypeScript 列舉型別TypeScript型別
- 透過列舉enum實現單例單例
- dedecms聯動型別裡,知道列舉值,如何轉換為列舉名型別
- 列舉和列舉的取值範圍
- 選單(轉)
- C# 列舉遍歷和轉換C#
- 【轉】Java 列舉7常見種用法Java
- 再談在Java中使用列舉(轉)Java
- JAVA 基礎 - ENUM 列舉的簡單使用Java
- ZwQuerySystemInformation列舉核心模組及簡單應用ORM
- 列舉單例模式如何防止反射攻擊單例模式反射
- Java列舉Java
- Swift,列舉Swift
- 7.1 實現程式記憶體塊列舉記憶體
- Object C學習筆記19-列舉Object筆記
- 記一個TS 列舉順序的坑
- 2、全域性變數和列舉常量 (轉)變數
- Effective Java - 構造器私有、列舉和單例Java單例
- 單例模式中為什麼用列舉更好單例模式
- 列舉的幾種使用案例(簡單,進階,switch,單例)單例
- c#列舉與陣列初始化及使用小記C#陣列
- Swift列舉關聯值的記憶體探究Swift記憶體
- C# 列舉與位列舉概述C#
- 列舉工具類
- TypeScript 列舉enumTypeScript
- Java 列舉(enum)Java
- Swift-列舉Swift
- 自定義列舉