Menu ▾ ▴

#25 Allow enumerating the popup menu of a control, showing it and clicking an entry

open
nobody
None
2026-10-16
2026-10-16
No

MENU and MENUCLICK reach only the IDE's main menu (TryGetIdeMainMenu in ide/GxInspect_Ide.pas). A control's popup menu cannot be listed or clicked as a menu. COMPONENTS lists a TPopupMenu and the items created at design time, but only by class and name: no captions, no state, no tree, and none of the items added at run time. CLICKAT sends only the left mouse button. KEYS <form> <control> Shift+F10 does open a control's popup menu, and while it is open, KEYS with the arrow keys, Enter and Esc can operate it. (KEYS ... Apps does not open it: no WM_CONTEXTMENU arrives.) What is missing is a way to see what is open: no command lists the open menu and its items, and SCREENSHOT captures only the form, not the menu. Many GExperts dialogs do much of their work through popup menus, e.g. the Uses Clause Manager has six of them (pm_Intf, pm_Impl, pmuAvail, pm_Favorite, pmCopySaveProjectList, pmUCMStatusBar).

Proposed commands, with the menu path as MENU takes it (steps separated by |, each a component name or a caption):

  • POPUPMENU <form> <control> [<path>] lists the items of the control's popup menu, or the branch that a path names.
  • POPUPCLICK <form> <control> <path> clicks an entry, with the same checks and the same deferred click as MENUCLICK, so a dialog it opens holds nothing up.
  • POPUPSHOW <form> <control> [<x> <y>] opens the menu at a point in the control's client coordinates, by default the centre. KEYS ... Shift+F10 already opens it, but not at a chosen point, and only for a control with a window of its own.
  • A command that lists the menu that is open just now, whichever way it was opened, with its items and the highlighted one, e.g. OPENMENU.
  • SCREENSHOT of the open menu, e.g. SCREENSHOT MENU <file>, or the form together with the menu in front of it.

Things to get right:

  • Which menu: TControl.PopupMenu is protected, so it is read through the published property or a cracker class. A control without one shows its parent's menu, since the VCL passes WM_CONTEXTMENU on to the parent, and OnContextPopup can show a different menu or none. The answer should say which menu was used and which control it belongs to.
  • Items added on opening: many menus fill or update their items in OnPopup, and handlers often look at PopupComponent. Listing and clicking therefore set PopupComponent to the control and call DoPopup first (protected and virtual in TPopupMenu, already in Delphi 6), and bring each item up to date with InitiateAction, as MENU does.
  • Showing: TPopupMenu.Popup does not return until the menu is closed, so POPUPSHOW has to answer first and open the menu afterwards, like MENUCLICK. The server stays usable meanwhile: the menu loop goes on dispatching messages, including those to the server's hidden window, so the commands that run in the main thread are still answered while the menu is open (measured). Sending WM_CONTEXTMENU to the control would be the most faithful way, since it also runs OnContextPopup.
  • Seeing the open menu: the open menu is a window of class #32768, which is neither a form nor a control of one. Its items can be read from the HMENU it shows (MN_GETHMENU, then GetMenuItemInfo, with MFS_HILITE for the highlighted item) and matched to the TMenuItems by their command ids. Capturing it needs a screenshot of that window, not of the form.
  • Where the code lives: none of this needs the IDE, so it belongs in the core. The menu path helpers ResolveMenuPath, FindMenuStep, DescribeMenuItem, ListMenuItems and WhyMenuItemCannotBeClicked are pure VCL as well, and could move with it; see also ticket #24 (ACTION and ACTIONS into the core).

Discussion


Log in to post a comment.