问题
Normally when you hover over a sub-menu (with the little arrow) on a CMenu menu item it delays briefly then shows the sub-menu items. Also, if you click the item before the delay timeout, it shows the sub menu items. I want the delay behavior, but I want a different behavior for the click. That is, I want the sub-menu itself (the one with the arrow) to be a clickable entity too, i.e. it has an ID and results in a WM_COMMAND and menu dismissal.
The idea is, the main sub-menu menu item is a "default", and the sub-menu items are modified versions, e.g. "print->" (defaulting to default printer), and sub-menu items like "print preview" "print to file" etc. Thanks for thoughts/suggestions.
edit:
IDR_MY_MENU MENUEX
BEGIN
POPUP "menu"
BEGIN
MENUITEM "&Something Else", ID_MENU_SOMETHING_ELSE
POPUP "&Print", ID_MENU_PRINT
BEGIN
MENUITEM "Print Pre&view", ID_MENU_PRINT_PREVIEW
MENUITEM "Print to &File", ID_MENU_PRINT_TO_FILE
END
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM "&Bottom", ID_MENU_BOTTOM
MENUITEM "&Done", ID_MENU_DONE
END
END
回答1:
I dont know if theres a better way as I last did this 2 years ago, but the way I solved the problem had one constraint: that you own the whole menu. If you do own the whole menu what you can do is create two columns (two columns in the menu/submenu that is, not a new submenu) and use the right column as a submenu and the left column as the default.
回答2:
For future StackOverflowers, here's what I did...
- Added a handler for
OnInitMenuPopupand correspondingON_WM_INITMENUPOPUP(), although doing this messed up myUPDATE_COMMAND_UIhandler but I was able to resolve that by moving that code into theOnInitMenuPopuphandler. - In the
OnInitMenuPopuphandler, set a hook for the mouseSetWindowsHookEx(WH_MOUSE,...)(checking if one isn't already set because sub-menus can cause multiple calls)... and for each menu that initializes during the hook, push theHMENUonto a linked list. - In the mouse hook proc, checking the end of the list and working toward the front, verify each
HMENUis still and active menu viaIsMenuand remove it if it isn't. If there are no menus left,UnhookWindowsHook. - If there are menus left in the hook proc, check for
WM_LBUTTONUPorWM_RBUTTONUPand see if happened over one of your menu items (because of coordinate mapping of screen versus sub-menu that I couldn't figure out I ended up simply cycling through the menu items viaGetMenuItemRectand checkingPtInRectto determine this). - If there is a click hit, do
GetMenuItemInfoon the item, and if there's ahSubMenufor that item and it has anwID(and thewIDdoesn't match the sub-menu handle), simply post the id as aWM_COMMAND, post aWM_CANCELMODEto dismiss the menu, and disable the hook... Bingo!
So, seems to work fine and everything else functions like normal. The only issue at this point is a keyboard handler for selecting the item instead opening the sub-menu but I suspect the same idea works there as well.
Also, I added the main sub-menu text as the first item in the sub-menu list with a separator which added some clarity to what the menu was doing.
来源:https://stackoverflow.com/questions/28331180/how-can-i-make-a-cmenu-trackpopupmenu-submenu-menu-item-clickable