First on the list of non-visual objects, I decided to describe the menu. Although the "non-visibility" of this object is quite possible to question. The main menu is a completely visual element of the form, although it does not have its own window descriptor (of course, the menu has descriptors, but they are not window descriptors).
Moreover, the main menu is displayed on the form, including at the design stage, allowing you to create event handlers (and quickly jump into their code) when you select the appropriate item in the menu. Note: however, unlike VCL, to create new main menu items, or to move items, in MCK you should use the menu editor, which is invoked by double clicking on the mirrored component.
In the KOL library, the main menu, the popup menu, and the menu items are all implemented in one TMenu object, keeping the tradition of saving on a variety of objects. The menu builder uses a list-of-strings-based templating technique, similar to the one used for the toolbar. Historically, the menu was developed earlier than the line of buttons, and this method of economical construction of multi-element objects was used for the first time precisely to build a menu tree. Digging even deeper, this object first appeared in XCL, the predecessor of KOL, and little has changed since then.
When you create the first menu and assign it to a form, this menu object is automatically made the main menu for the form (and if it has at least one item, it is displayed at the top of the form). All subsequent menu objects added to the form become popups and are not displayed until either the Popup or PopupEx method is called programmatically or automatically (SetAutoPopupMenu) for them. In particular, if the form should not have a main menu, but it has one or more pop-up menus, then the first step is to add a dummy main menu that does not have displayed elements.
Constructors:
NewMenu(Parent, dummy, template, onmenu) - constructs a menu based on the specified template, adding it to the form specified by the Parent parameter;
NewMenuEx(Parent, dummy, template, onitems_array) - similar to the previous function, but allows you to assign your own event handlers for all or part of the menu items at once.
The dummy parameter was retained for compatibility with the first versions of KOL when it was used and named maxcmdreserve (and then firstcmd). Since the menu for each item began to create its own instance of the TMenu object, the need for this parameter has disappeared.
The rules for constructing a template template should be discussed in more detail. Template is an array of strings (of type PChar) that define for menu items:
•their appearance (text, mnemonics, accelerators);
•mode of operation (normal, separator, switchable, groupable radio switch, initial state of the switch).
To specify all these features, prefix characters in strings are used:
'&' |
The character before the letter or number that becomes the mnemonic of the menu item. The mnemonic is displayed with an underline (in newer versions of the OS, by default, the underline is shown only when the Alt key is pressed), and allows you to invoke a menu from the keyboard. Let me remind you that in order for the KOL application to be able to use mnemonics in the menu without first activating the menu itself, you must provide a call to the SupportMnemonics method; |
'+' |
The menu item is "marked" with a special checkmark. For radio-toggled menu items, a circle is used instead of a checkmark. If such a prefix is specified before the text of an element, then the element becomes automatically switchable. In this case, when a user selects a menu item, it automatically changes its state from "checked" to "not checked". If the prefix '+' (or '-', see below) is followed by a '!', Then the menu item is radio switchable. The system combines several consecutive radio switches into one group automatically (there should not be other types of menu items between them); |
'-' |
The menu item is "unchecked", but otherwise everything said about the '+' prefix is also true for '-'; |
'-' |
If the text of an element consists of a single minus, then the element is a separator (and is shown in the menu as a narrow line between groups of regular menu elements). The separator is always not selectable, and therefore it doesn't make sense to assign an OnMenu event handler to it; |
'(' |
Starts a submenu subordinate to the previous menu item; |
')' |
Ends the submenu, returning to the previous nesting level. |
In the NewMenuEx constructor, as well as in the AssignEvents method, when events from an array parameter are assigned to menu items, separators and template elements '(' and ')' are not taken into account (skipped).
Properties, methods and events of the TMenu object:
Handle - menu descriptor. The menu itself and any of its elements (including separators) have such a descriptor. This descriptor is a number (of the hMenu type) known to the system, and allows you to call API functions to perform some kind of action on the menu at a low level. For example, a menu, along with all its submenus, can be passed as a parameter to the TrackPopupMenu and TrackPopupMenuEx functions to "pop up" the menu with any additional display styles;
SubMenu - descriptor of the subordinate menu. In fact, equivalent to Handle;
MenuID - internal numerical "identifier" of the menu item, assigned by the KOL code. Because the number of available identifiers cannot exceed 65535, and these identifiers cannot be reused, then you should not constantly create and delete menu items too often during long-term work. In particular, you should not make them "hidden", because hiding and showing menu items is implemented exactly as destruction and creation of new items (in Windows there is no way to hide menu items in a different way). Instead, it is recommended to use the ability to make menu items unavailable or available (enabled) as needed;
Insert(i, s, event, options) - adds a new menu item (creating another TMenu object corresponding to the newly created menu item, and returning a PMenu pointer to this object;
Parent - parent menu (if available);
TopParent - top-level parent menu;
Owner - an object of type TControl to which this menu belongs (must be a form);
Items[i]- subordinate menu items (including nested menu items, including separators). The i parameter can be the absolute index of the nested element with a value between 0 and 4096, or a numeric ID descriptor. A value of -1 returns the menu item itself (itself);
Count - the number of subordinate menu items, including recursively nested items;
IndexOf(s) - returns the index of the subordinate menu item (including nested items of any level), searching for it by the text s. A value of -1 is returned for the menu item itself, and -2 if no such menu item is found;
InsertSubMenu(submenu, i) - allows you to add a previously prepared menu as an element of this menu, along with all its subordinate elements;
RemoveSubmenu(i) - detaches a subordinate menu added, for example, by the InsertSubMenu method;
AddItem(s, event, options) - adds a menu item to the end of the list;
InsertItem(i, s, event, options) - inserts a menu item at the specified position;
AssignBitmaps(i, bitmaps) - allows you to assign several bitmaps at once to menu items, starting with a given one;