By default when you select an item from a TMainMenu or TPopupMenu etc, the menu closes after it was clicked. I would like to change this behavior so that when I select on a menu item, the menu does not close but remains visible and open at the point it was last clicked, making it easier to select another menu item if desired. Of course, switching focus to another control should hide the menu like normal, but if the focus is still on the menu keep it visible.

If this is possible, I would like this behavior to only work on specified menu items. In other words, if I can make all the menu items work like normal, but if I specify one or two menu items, these will not close the menu when selected.

The reason I want to do this is like so, I have a Preferences form in my Application where many options can be configured, the usual stuff etc, but also in the Main Form I have some of the common more frequent used options set in a TMainMenu. These common options in my menu I would like to be able to select without closing the menu, so that other options can be selected for example without having to navigate through the menu items.

+1. Within a few minutes, a lot of 'nitpickers' will argue that this is not the default Windows design, and that this will confuse the end user. However, to your defence, you can argue that the status bar context menu in Microsoft Office (2010 at least) applications, to name only one example, behaves like this. And this is a very good thing, for this context menu contains only check-box items, and you are likely to click quite a few of them in a row.
–
Andreas RejbrandMay 12 '11 at 19:22

Well I dont have Office 2010, but looking from the screenshot in the link provided it appears to do something similar to what I want, the only difference being is I am using a standard TMainMenu.
–
user741875May 12 '11 at 19:30

I think that's going to be tough to achieve with a standard menu.
–
David HeffernanMay 12 '11 at 19:47

1

@andreas you are often one of the chief nitpickers arguing in favour of standard UI. Have you reformed? ;-)
–
David HeffernanMay 12 '11 at 19:48

1

I wonder if the TActionMainMenuBar can be modified to achieve this (of course, only when the action manager's Style <> Platform default ).
–
Andreas RejbrandMay 12 '11 at 20:02

4 Answers
4

In the below code, when right clicked on the panel on the form, a popup menu with three items is launched. The first item behaves normally, the other two items also fires their click events but the popup menu is not closed.

The popup is launched with 'TrackPopupMenu', if instead you'd like to use 'OnPopup' events, or need to use sub menus having non-closing items, refer to the link in the comment I posted to your question. Adapting the code for a main menu would not be difficult as well..

I'm not commenting the code not to promote the usage of the approach since it makes use of an undocumented message, also I feel it is a bit convoluted..

excellent job, I have tested and this works perfect with popupmenu. I will check out the link you posted to see if I can adapt for main menu. Your answer has been accepted thanks.
–
user741875May 13 '11 at 9:11

@Craig, thanks, and you're welcome! The answer I referred in the comment is rather relevant with popups that are launching automatically ('PopupMenu' property of controls), and also mentions few things which are ignored in this answer, like sub-menus, accelerator keys (more work to do..). Possibly you'll have to think of some other special cases as well, f.i. disabled items.. I believe main menu handling would be similar to this answer because menu messages are sent to the form..
–
Sertac AkyuzMay 13 '11 at 11:17

nice answer and +1. I posted a question which turned to be a duplicate. but there is a small problem with your code: if I set Item.Checked := not Item.Checked right after Item.Click; (MenuSelectID) - The Item is not invalidated, and the check is not drawn until I leave the Item area and Enter back to it :( What can be done?
–
ZigiZJan 6 '13 at 15:46

My guess is that although this is acceptable, you should probably consider writing your own menu system, using Panels or forms, or a complete custom control/component set, and not use the standard TPopupMenu or TMainMenu at all if you want to do this.

If you want some starter source code, I would start with something like the Toolbar2000+SpTBX Sources. I am pretty sure you would be able to accomplish this using those, but not with TMainMenu and TPopupMenu, because they wrap some Win32 builtins that will have behaviours (including closing when you don't want to) that it's not possible to override.

You might also be able to do something like this out of the box with the Developer Express toolbar components.

a few very good suggestions there. The panel/form idea is probably not feasible however, especially since it would mean alot of work maintaining it (items, images etc). I dont have the DevExpress component suite which I know you have to pay for.
–
user741875May 12 '11 at 22:02

I had the same need recently and found that TMS Smooth controls has "tear off" menus which has a similar function but require (as indicated by the name) that the menu be, um, torn off! I never looked into to, because my need wasn't strong enough to justify the time, money, or use of a third party product. But, I've used other stuff of theirs that has been first rate.

Not sure if their tear off menus would fill your needs, but you might want to look into it.

Based on @Sertac's code and other resources, I have made a small unit which makes an Interposer class of TPopupMenu and TMainMenu (also for TNT versions).

It handles sub-menus also (each time a sub-menu is activated, a new menu window is created with new menu handle).

The idea was to create an application-defined hook (WH_CALLWNDPROC) with a lifetime as short as possible. The hook will be active only as long as the menu modal loop is active. Once the hook detects a new Popup window handle (via WM_ENTERIDLE), it then subclasses it until it is destroyed.

Drop a TPopupMenu and/or TMainMenu on the form. in the uses include AppTrackMenusafterMenus. Create some menu items and for each menu item you want to not be closed when clicked, set Tag=666 (for this example). You can assign each of these items an OnClick event handler CheckNoCloseClick.

The TMainMenu Interposer could be improved by sub-classing it's Form at run time, on demand (by setting a new Form.WindowProc) without the need of overriding WndProc for each Form. But ,there is usually only one main menu per application. Maybe next version... :)