// // GetMenuHctl // // this code demonstrates, how one can get a menu's control handle in a // custom control for VB2. It can be used e.g. during the processing // of WM_MENUSELECT to get the tag property of a menu entry. // // the code is taken (with some modifications) from the last version of my // status bar control, where it is used to fire the SelectedTag event. // I will upload the control within the next days. // // Input: HWND hWndForm window handle of the form // WORD wp see SDK documentation for WM_MENUSELECT // LONG lp ... // // Return: hctlMenu control handle (or NULL) // // THIS CODE USES UNDOCUMENTED FEATURES OF VB2, AND THERE WILL BE CHANGES // NEEDED FOR FUTURE VERSIONS. WE ALL SHOULD HOPE, THAT MS WILL MAKE THE // CONTROL HANDLE OF MENU ITEMS AVAILABLE WITH AN API CALL. // // I had a similar routine working for VB1 (see version 1.x of StBar), but // it could not be ported to VB2, becaused it depended on assumptions on // the messages, message ordering, and menu item ids. // // Any comment to this is welcome // // Bernd Beekes, 100031,2063 // #include #include #define MENU_OFFSET 7 #define ITEM_OFFSET 8 #define MENU_CONTROL "MENU" HCTL NEAR GetMenuHctl(HWND hWndForm, WORD wp, LONG lp) { HMENU hMenu; SHORT fwMenu; HCTL hctl; HCTL hctlMenu; SHORT nMinItem; WORD nItem; LPMODEL lpModel; LPSHORT lpMenuStruct; LPSTR lpszName; // get menu handle and flags fwMenu = LOWORD(lp); hMenu = (HMENU) HIWORD(lp); // ignore menu closing, separators, system menu, ... if (hMenu == 0) return NULL; if (fwMenu & MF_SEPARATOR) return NULL; if (fwMenu & MF_SYSMENU) return NULL; // determine menu handle and item number if (fwMenu & MF_POPUP) { hMenu = (HMENU) wp; nItem = 0; } else { nItem = wp; } // initialize variables and walk thru control collection nMinItem = -1; hctlMenu = NULL; hctl = VBGetHwndControl(hWndForm); hctl = VBGetControl(hctl, GC_CHILD); hctl = VBGetControl(hctl, GC_FIRSTCONTROL); while (hctl != NULL) { lpModel = VBGetControlModel(hctl); lpszName = (LPSTR) MAKELONG(lpModel->npszClassName, (_segment) lpModel); if (lstrcmpi(lpszName, MENU_CONTROL) == 0) { lpMenuStruct = (LPSHORT) VBDerefControl(hctl); if ((HMENU) *(lpMenuStruct + MENU_OFFSET) == hMenu) { // for menu items the item id is at lpMenuStruct + ITEM_OFFSET if (nItem != 0 && (WORD) *(lpMenuStruct + ITEM_OFFSET) == nItem) { hctlMenu = hctl; break; } // for pop up entries, look for the entry with minimal id !!! if (nItem == 0) { if (nMinItem == -1 || nMinItem > *(lpMenuStruct + ITEM_OFFSET)) { nMinItem = *(lpMenuStruct + ITEM_OFFSET); hctlMenu = hctl; } } } } hctl = VBGetControl(hctl, GC_NEXTCONTROL); } return hctlMenu; }