Menu enumeration
There is an MDI application that is now assumed to enumerate it to get the content of the system command to respond to all menu items: If the command ID, the resource name, the (child) handle, etc., and operate it. This article is a bit two or two, and it is expected to be in the depth of Han, and the only one is in the same place.
1, my confusion
These days have cultivated ENGLISH HELP, so that they have a little fruit, I hope to have a total of the world, and I don't know if it is effective, but it is Master-class:
The menu item can be a menu, and vice versa, the menu is called a submenu; if the menu item is not a menu, it is 'pure menu item'. I used to think that every item in the menu is a menu, therefore no need for menu items in my thinking. Maybe this is a rookie-level problem, but you may not have much mellow, then you may wish to talk on the paper, draw a picture of the simplest menu, and ponder.
2, menu enumeration algorithm
A, one of the menu abstract structures (tree type abstraction):
Now you have to access all of the leaf nodes of this 'tree' and processed, as described B.
B, enumeration algorithm (depth traversal, C syntax)
1.) Quality of the child nodes of the current node.
2.) Cycle query the current node i (0 <= i If the sub-node i does not subtract the sub-node, then the sub-node I is the leaf junction. After processing, I = i 1, repeat this step; Otherwise, the sub-node i is a branched node, and the lower sub-node is the current node, and turn to 1; 3. The traversal is over. INT FindMenuItem (HMENU HMENU) // Parameter HMENU is identified for branch node resource { 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.dewtypedata = s; c = getMenuItemCount (HMENU); // Get all the number of menu items all of the current menu For (i = 0; i { mii.cch = 32; // pay attention! Res = GetMenuItemInfo (HMENU, I, True, & Mii); IF (res == 0) {delete S; return -1;} // If the menu information failed IF (mii.hsubmenu == NULL) // { // If the menu item is a non-submenu, it will be processed here. } Else { // If the menu item is a submenu, Res = findMenuItem (mii.hsubmenu); // Direct recursive call IF (res == - 1) {delete s; return -1;} } } Delete S; Return 0; } INT EnummenuendItems (HWND HWND) // Start Traverse Window menu item. The parameter hwnd is the form where the menu is located. { HMENU HMENU = GetMenu (hwnd); IF (HMENU == Null) Return -1; Return FindMenuItem (HMENU); } Note: The code here only describes the algorithm. If it is applied to it, according to different needs, the return value and node processing code of Function will change. Appendix 2 is a PB text of the above code, both slightly, with reference. The Windows API and Struct used in the above code are slightly clicked. 3, in the development tool used in the development tools, the following Windows API and related struct (standard format): HMENU GETMENU (HWND HWND); // Return Value: Menu handle of the window associated with HWND HMENU GetSubmenu (HMENU HMENU, INT NPOS); // Return Value: The child of the nodes in the menu associated with HMENU INT getMenuItemcount (HMENU HMENU); // Return Value: Number of menus items in the menu associated with HMENU Bool WinAPi GetMenuItemInfo Hmenu Hmenu, Uint UItem, BOOL FBYPOSITION, / / This parameter determines that the command ID of the current menu item or the sort position number in the belonging menu LpMenuItemInfo lpmii); Bool DrawMenuBar (HWND HWND); / / Re-painting the menu of the window associated with HWND Typedef struct tagmenuiteminfo { Uint Cbsize; // This structure is physical size, based on byte, its value is actually 48 UINT FMASK; / / Determine what you want to query or set the menu item Uint ftype; // menu format type Uint fstate; // menu status: enabled, disabled or grayed UINT WID; / / Command Identifier HMENU HSUBMENU; // Submenu handle, if there is no submenu, null Hbitmap hbmpchecked; // According to these two domain values, you can customize the marker when the menu item is selected. Hbitmap hbmpunchecked; //, not necessarily '√' or blank DWORD dwitemdata; // Translated from English as: Application defined value related to menu items (I don't understand) LPTSTR DWTYPEDATA; // Menu Resource Content Pointer, pointing to String OR Bitmap or Separator resources UINT CCH; // If the menu item is the MFT_String type, this is Dewtypedata length Hbitmap hbmpitem; // found this one when debugging Menuiteminfo, FAR * LPMENUITEMINFO; Reference: MSDN98 (Microsoft) MS SDK HELP FILES / WIN32 Developer's References (Inprise / Borland) (Appendix 1 is a declare text of the above API in PB) Windows API functions related to MENU operations is also more, moderate reference, dynamic library: USER32.DLL. 4, other: A, I call these Windows features in PB7, but when debugging to getMenuItemInfo, single-step running is stagnant, about After 30 hours, I conducted the following: A1, open a DOS window, run TDUMP C: /WINDOWS/SYSTEM/User32.dll> user32.txt (TDUMP.EXE is Inprise Application) A2, return to Windows, open user32.txt with Notepad, found that there is no getMenuItemInfo, but there is GetMenuItemInfoa, if you call Win API in VB, you can speculate. A3, rewrite the GetMenuItemInfo (or alias) into getMenuiteminfoa, you will be OK! B, menu item command identifier After calling GetMenuItemInfoa, its value is saved in Menuiteminfo :: WID. Setting Now, a menu item is now stored in the Menuiteminfo type Structural MII, and its part is: mii.cbsize = 48 mii.dewtypedata = "Open File" mii.wid = 10001 mii.fstate = enabled mii.ftype = mft_string Corresponding function reference identity command identifier WID Openfile () 10001 Closefile () 10002 WID = 10001 C, when the above GetMenuItemInfoa is called, the following domains of Menuiteminfo are required: Menuiteminfo :: CBSIZE Menuiteminfo :: Fmask Menuiteminfo :: DWTYPEDATA Menuiteminfo :: cch Where Menuiteminfo :: Fmask can be a combination of constant values (it is difficult to find these constant values in related materials) MIIM_STATE (= 1) miim_id (= 2) MIIM_SUBMENU (= 4) MIIM_CHECKMARKS (= 8) MIIM_TYPE (= 16) MIIM_DATA (= 32) Attachment: 1, related API and structural declare in PB 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 Enablemenem (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 Dewtypedata Unsignedlong Cch Long HBmpItem End Type 2, PB code, different from C code (excellent selection, modification) as needed 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. 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 Commits. 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 ("", "some operations may no longer exist, but users still have the operation permission, please delete manually!") Return 0 Error: Rollback. 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.dewtypedata = "" " 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; // save the 'pure' menu item information IF trans.sqlcode = -1 Then return -1 Case 1 Update sec_fun set handle =: hmenu where id_fun =: mii.wid sale trans; IF trans.sqlcode = -1 Then Return -2nd 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