Difference between revisions of "MenuItem"

From Xojo Documentation

(See Also)
Line 1: Line 1:
{{SupportedPlatforms | type = d}}
{{SupportedPlatforms | type = d}}
{{WebApp | link = [[WebMenuItem]]}}
{{WebApp | link = [[WebMenuItem]]}}

Revision as of 20:47, 13 September 2021

For web apps, see WebMenuItem.

Class (inherits from Object)

An individual menu item in a desktop project. Used by menu bars and contextual menus.

Action EnableMenu
AutoEnabled HasMacOptionKey fa-lock-32.png Name
Enabled HasSecondaryModifierKey fa-lock-32.png Shortcut
Handle fa-lock-32.png HasStandardModifierKey fa-lock-32.png ShortcutKey fa-lock-32.png
HasAltKey fa-lock-32.png Icon Tag
HasCheckmark Index fa-lock-32.png Value
HasMacControlKey fa-lock-32.png LastRowIndex fa-lock-32.png Visible
AddMenu Close Remove
AddMenuAt Count RemoveMenuAt
Child MenuAt
Clone Popup

Constructor(Text as String, Tag as Variant)

Class Constants

The following class constant is used to add a separator item to a menu. Use this constant to add a separator with the AddMenu or AddMenuAt methods:

Class Constant Description
TextSeparator A menu separator.


MenuItem objects are used to create and access the properties of menu items. You can change the menu item text using the Value property. You can find out if a menu item is checked, or check or uncheck a menu item with the HasCheckmark property. You can also enable or disable a menu item using the Enabled property. The Enabled property should be set only from within an EnableMenu event handler. Setting it from anywhere else has no effect.

Three other classes handle specialized menu items. QuitMenuItem is designed to manage the File→Quit (File→Exit on Windows and Linux) menu of a built application; it is enabled by default and automatically calls the Quit method. The PrefsMenuItem class is designed to handle the Preferences menu item. In macOS, this menu item is supposed to be located under the application's menu, but on other operating systems, this menu does not exist. A menu item derived from the PrefsMenuItem class automatically appears under the application's menu under macOS; on other operating systems is appears where you put it in the Menu Editor. The ApplicationMenuItem class is designed for creating menu items that appear under the application's menu on macOS. Any menu subclassed from ApplicationMenuItem will move to the application's menu for your macOS build but stay where it is for your other builds.

MenuItems can be created on the fly using the New operator or the Clone method.

Contextual Menus

Use The ConstructContextualMenu and ContextualMenuAction events of the RectControl or Window to create and manage contextual menus.

MenuItems on Mac

The Mac framework does not allow a MenuItem to be used in different places, e.g. several MenuBars. Trying to do so will raise a MenuHasParentException. In order to avoid the hassle of creating several times the same MenuItem, you can use the Clone method to make copies.

Specifying the keyboard shortcut in the Menu Editor

When you use the Properties pane in the Menu Editor, you specify the menu item's shortcut key by assigning a key to the ShortcutKey property and (normally) at least one modifier key. The Menu Editor translates your settings into the value for the Shortcut property.

You can use either a printable key or the following non-printable keys as shortcut keys: F1-F15, Tab, Enter, Space, Del (Delete), Return, Bksp (Backspace), Esc, Clear, PageUp, PageDown, Left, Right, Up, Down, Help, and Ins (Insert). If the shortcut key is more than one character and it is being set via code, the modifier key is not implied and must be explicitly defined. For example, the following line sets the Tab key as the shortcut key and uses the Ctrl key as the modifier.

SpecialMyMenuItem.Shortcut = "Ctrl-Tab"

For macOS, use "Cmd" instead of "Ctrl." Or set the HasStandardModifierKey property to True in the IDE and pass the string literal for the desired keyboard shortcut.

Other values you can use are: "Opt", "Alt", "Shift". You can combine keys like this:

MyMenuItem.Shortcut = "Shift-Ctrl-W"

When you are setting a non-printable key in the IDE, you can just enter its name from the list above and check the desired modifier key from the following list.

The ShortcutKey property entry and the entries for the modifier keys are described in the table below.

Name Description
HasSecondaryModifierKey The Shift key on all platforms. If selected, the Shift key must be held down while pressing the value of the ShortcutKey property to trigger the event handler of the MenuItem.
ShortcutKey The shortcut key for the menu item. If this key and the selected modifier keys set is held down, the event handler for the menu item will be executed as if the menu item itself were chosen via the mouse pointer.
HasMacControlKey The Control key on Mac. This property is Mac-only. If selected, the Control key must be held down while pressing the value of the ShortcutKey property in order to trigger the event handler of the menuitem.
HasMacOptionKey The Option key on Mac. This property is Mac-only. If selected, the Option key must be held down while pressing the value of the ShortcutKey property to trigger the event handler of the menu item.
HasStandardModifierKey The Control key on Windows and Linux and the Command key on Mac. If this property is selected, the HasStandardModifierKey key must be held down while pressing the key specified by the ShortcutKey property to trigger the event handler for the menu item.
HasAltKey The Alt key on Windows and Linux keyboards. If selected, the Alt key is must be held down while pressing the value of the ShortcutKey property in order to trigger the event handler for the menu item. This property is for Windows and Linux only.

Sample Code

The following code changes the text of the EditPaste menu item to "Paste Special…":

EditPaste.Value = "Paste Special..."

The following code adds a new item in the Edit menu with the text "Paste Special..." just below the Paste item.

Var EditPasteSpecial As New MenuItem
EditPasteSpecial.Value = "Paste Special..."
EditMenu.AddMenuAt(5, EditPasteSpecial)

Using the constructor, you can write:

Var EditPasteSpecial As New MenuItem("Paste Special...")
EditMenu.AddMenuAt(5, EditPasteSpecial)

The following code adds a Select All menu item to the Edit menu.

Var EditSelectAll As New MenuItem
EditSelectAll.Value = "Select All..."

The following code gets the MenuItem corresponding to the Cut item on the Edit menu.

Var c As MenuItem
c = EditMenu.Child("EditCut")

The following code gets the MenuItem corresponding to the Cut item on the Edit menu by position:

Var c As MenuItem
c = EditMenu.MenuAt(2)

The following code removes the fourth dynamically created menu item from a menu item array named WindowItem:


The following code assigns a value to the Tag property of a menu item:

SearchFind.Tag = "UserSearch"

Contextual Menus Code Samples

The following code displays the Edit menu as a contextual menu. The code is in the MouseDown event handler of a RectControl. You can get the text of the selected item by accessing the Text property of the returned MenuItem.

If IsContextualClick Then
Var m As MenuItem
m = EditMenu.Popup
End If

In general you should create and display contextual menus using the ConstructContextualMenu and ContextualMenuAction event handlers of the Window and RectControl classes. They are fully cross-platform and don't make assumptions about how the user requested a contextual menu.

The following code creates a contextual menu in the ConstructContextualMenu event of any Window or RectControl. This event passes in the parameter base as MenuItem.

base.AddMenu(New MenuItem("Import"))
base.AddMenu(New MenuItem("Export"))
base.AddMenu(New MenuItem(MenuItem.TextSeparator))

base.AddMenu(New MenuItem("Cut"))
base.AddMenu(New MenuItem("Copy"))
base.AddMenu(New MenuItem("Paste"))
Return True // display the contextual menu

The following code in the ContextualMenuAction event handles the menu selection. This event passes in the parameter hitItem as MenuItem. This is the selected menu item.

Select Case hitItem.Value
Case "Import"
MessageBox("You chose Import")
Case "Export"
MessageBox("You chose export")
Case "Cut"
MessageBox("You chose Cut")
Case "Copy"
MessageBox("You chose Copy")
Case "Paste"
MessageBox("You chose Paste")
End Select

Return True

Dynamic Menus Code Samples

In certain cases you cannot specify the menu items that belong in a menu in advance. They may change depending on the context in which the application is used or on the operating system on which the application is running.

A common example of this is the Font menu that is normally included in any application that supports styled text. The programmer has no way of knowing in advance which fonts happen to be installed on the user's computer. The Font menu's menuitems have to be built dynamically when the application is launched.

The recommended technique is to create a subclass of MenuItem in the Project Window. To create the menuitems, you use the MenuItem's constructor to instantiate an instance of the class for each menuitem you need. You handle the menuitem in the Action event.

You then write code to populate the menu with the names of the fonts installed on the user's computer. If we assume that fonts won't be added or deleted while the application is running, we can build the font list when the application launches. You can do this in the App.Open event or the Open event of a window if the menu should appear only for a particular window. This example uses the App.Open event.

Before adding the App.Open event, we will add a MenuItem subclass to the project. We will name it "AddFont" and set its Super class to MenuItem. It will use the constructor to add each menuitem. The constructor takes the MenuItem’s text as its parameter. The optional rowtag parameter is not used. Since the constructor is built-in, you do not need to explicitly add a constructor to your code.

The MenuItem subclass has two events, Action and EnableMenu. You do not need to use EnableMenu because AutoEnabled is True by default. You do need to add code to the Action event. This is the code that will run when a user selects a menuitem. It serves the same purpose as the Menu Handler that is used for static menuitems.

In this case, we want the menu item to set the selected text in a TextArea to the font that the user chose. The Action event is:

TextWindow.TextArea1.SelectionFontName = Me.Value
Return True

TextWindow is the name of the window that contains the TextArea and TextArea1 is the TextArea. The Text variable holds the font name that was passed to AddFont when the font was created.

Next, we want to add code to the Application.Open event to create the Font menu and populate it with the name of the user's installed fonts. The following code adds the Font menu to the default menubar:

Var m, mNew As MenuItem
m = Self.MenuBar
mNew = New MenuItem
mNew.Value = "Fonts"
mNew.Name = "FontsMenu"

The next block of code populates the Font menu. It uses the built-in System.FontAt function which returns the name of the ith font on the user's computer. The code instantiates an instance of the AddFont subclass for each font:

Var child As MenuItem
If mNew = Nil Then
MessageBox("Menu parent is nil!")
End If

// build the font menu
For i As Integer = 0 To System.LastFontIndex
child = New AddFont(System.FontAt(i))

Note that the Menu Editor and associated Menu Handlers are not needed. The menu selection is handled by the Action event of the subclass of MenuItem.

Duplicate MenuItems

Using the same MenuItem in different places raises a MenuHasParentException. You should clone the MenuItems instead.

See Also

ApplicationMenuItem, MenuHasParentException, PrefsMenuItem, QuitMenuItem classes; IsContextualClick, Application.RefreshMenuBar functions, New operator.