PBToolboxAI v4 ← Site

menubar — u_pbt_menubar #

← Component reference · Guide contents

Application menu bar: menus, submenus, checkable items, separators, icons and shortcuts — all drawn by the library, with no Windows menu involved.

▶ See it live — Demo application, Menu bar tile: the preview, the code behind it and this page, side by side.


At a glance #

Userobjectu_pbt_menubar
Item classn_pbt_menubar_item (one item) · n_pbt_menubar_menu (one menu of the bar)
Used forGiving your window the application menu bar, themed like everything else
PrincipleYou declare the menus, then their items; every item is found again by its address menu/id

Quick start #

// window open event
uo_menus.of_add_menu(/*key*/ "file", /*text*/ "File")
uo_menus.of_add_item(/*keys*/ "file/open", /*text*/ "Open")
uo_menus.of_add_item(/*keys*/ "file/save", /*text*/ "Save")
// event ue_item_selected : (string as_keys)
choose case as_keys
	case "file/open"; of_open_document()
	case "file/save"; of_save_document()
end choose

The model: three levels, one key per level #

A menu bar has three levels, and each is addressed by its key:

LevelAdded byKey
The menu on the barof_add_menuits key, file
The item of a menuof_add_itemthe address menu/item, file/open
The sub-item of an itemof_add_itemthe address menu/item/sub-item, file/export/pdf — as deep as needed

A key is unique under its parent only: that is why an item is always designated by its full address, the menu first — never by its key alone. Two menus can therefore each have their own open item, and two submenus their own pdf (file/export/pdf, file/print/pdf), without clashing. A key holds neither / nor |, is not empty and does not start with __: the adds refuse it (-5), as they refuse an address already taken or a parent never added.

A separator has no key: of_add_separator draws a line at the end of a menu (file) or of the cascade of an item (file/export), and there is nothing to read back afterwards.


Properties #

PropertyTypeDefaultRole
is_theme_stylestring""Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_modestring""Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accentlong-1Accent colour of this component (-1 = the application accent, or the theme's)
is_tooltipstring""Plain tooltip shown when hovering the component
is_super_tooltip_titlestring""Title of the rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Body of the rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of the rich tooltip
ib_wrapbooleanfalsefalse (default): the bar stays on one line; the titles that do not fit, from the end, go into the dropdown of a chevron at its end (their entries as cascades), and the height no longer changes. true: the bar wraps and announces its new height (ue_auto_height) — what it did before the 4.0
ib_track_hoverbooleanfalseSubscription to ue_item_hover: without it the dropdowns do not even report the pointed entry — an event raised at every move of the pointer is only sent to an application that asked for it

Item properties — n_pbt_menubar_item #

Obtained through of_item(address) — of_item("file/export/pdf"). An address of one level names a menu, not an item: its handle changes nothing, use of_menu.

PropertyTypeDefaultRole
is_textstring—Changes the item's label, live
ib_enabledbooleantrueItem is active; a greyed item no longer answers clicks
ib_visiblebooleantrueEntry taken out of the list without being removed — submenu and shortcut asleep with it; it keeps its key and comes back as it was. An asleep shortcut keeps its chord: it does not reach your application either; is_shortcut = "" gives it back
is_shortcutstring""The accelerator displayed at the right of the item (Ctrl+S) — and armed: the chord raises ue_item_selected for that item wherever the focus is. A menu is where people learn the shortcuts of an application; a key shown that does nothing teaches the wrong thing. Keys: a letter, a digit, F1 to F24, Enter, Esc, Del, Insert, Home, End, PageUp, PageDown, and with Ctrl or Alt also +, -, ,, ., the arrows (Left…), Space, Tab, Backspace (Ctrl++ for zoom). A shortcut belongs on a leaf: on an item that opens a cascade it is neither shown nor fired. An empty string takes both away
ib_checkedbooleanfalseCheck mark in front of the item — for an option that goes on and off
is_imagestring""The item's icon, changed live: the item keeps its place in the list. Same paths as of_add_item (mono:, tint:, file.dll:NAME); an empty string takes it away
is_groupstring""Makes the item a radio item: the items of one group under the same parent exclude each other — checking one (ib_checked = true, or the user's pick) unchecks the others, and a round bullet replaces the tick. ue_item_selected still tells you which one was picked. An empty string makes it an ordinary item again
il_accentlong-1Accent of this item: its tick, and its edge while pointed at (-1 = the theme's)
il_back_colorlong-1Background of this item in the dropdown, at rest
il_text_colorlong-1Text colour of this item
il_back_color_hoverlong-1Background of this item while pointed at
il_text_color_hoverlong-1Text colour of this item while pointed at
is_tooltipstring""Kept and read back, but an item of the dropdown shows no tooltip: the native dropdown has none. Only the menu titles show theirs (of_menu)
is_super_tooltip_titlestring""Title of its rich tooltip — kept, not shown (see is_tooltip)
is_super_tooltip_textstring""Text of its rich tooltip — kept, not shown
is_super_tooltip_imagestring""Image of its rich tooltip — kept, not shown

Properties of a menu — n_pbt_menubar_menu #

Obtained through of_menu(key) — of_menu("file"). Colours and tooltip show on the menu title in the bar.

PropertyTypeDefaultRole
is_textstring—Caption of the menu, & included (mnemonic), changed without rebuilding the bar
ib_enabledbooleantrueGreyed menu: it no longer opens, its items and their shortcuts with it; the keyboard skips it
ib_visiblebooleantrueThe menu leaves the bar — items and shortcuts asleep with it — and comes back as it was. Asleep shortcuts keep their chord: it does not reach your application either
is_alignstring"start"u_pbt_menubar.ALIGN_END sets the menu at the end of the bar, like Help — with those that follow it in the same alignment, after it; ALIGN_START (default) puts it back among the others. Logical: the end is the left side in a right-to-left layout. With the chevron, the titles at the end fold first
il_accentlong-1Accent of this menu: a line under its title while its dropdown is open (-1 = none)
il_back_colorlong-1Background of its title, at rest
il_text_colorlong-1Text colour of its title, at rest
il_back_color_hoverlong-1Background of its title when hovered or open
il_text_color_hoverlong-1Text colour of its title when hovered or open
is_tooltipstring""Tooltip shown when the pointer rests on its title
is_super_tooltip_titlestring""Title of the rich tooltip of its title
is_super_tooltip_textstring""Text of that rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of that rich tooltip

Methods #

MethodRole
of_add_menu (string as_key, string as_text)Adds a menu to the bar. Returns 0 once applied, -5 when the key is refused (empty, holding / or a vertical bar, starting with __, or already taken), -2 when the component is not created
of_add_item (string as_keys, string as_text)Adds an item at its address: file/open in the File menu, file/export/pdf under the Export item, as deep as needed. Returns 0 once applied, -5 when the address is refused: fewer than two levels, an empty level, a key holding / or a vertical bar or starting with __, a menu or a parent item never added, or an address already taken. -2 when the component is not created
of_add_item (string as_keys, string as_text, string as_image, boolean ab_checked)Same, with the icon and the tick. To grey the item, now or later, use its handle: of_item(address).ib_enabled = false. Returns 0 once applied, -5 when the address is refused: fewer than two levels, an empty level, a key holding / or a vertical bar or starting with __, a menu or a parent item never added, or an address already taken. -2 when the component is not created
of_add_separator (string as_keys)Draws a separator line at the end of a menu (file) or of the cascade of an item (file/export). Returns 0 once applied, -5 when nothing was added at that address, -2 when the component is not created
of_add_header (string as_keys, string as_text) → longAdds a section header at the end of a menu (view) or of the cascade of an entry (view/panels): a title line over the entries that follow it, until the next header or separator. It is not an entry — never chosen, never counted by of_count, nor in the demo cap — and it is not drawn when every entry it heads is hidden. Returns 0 once added, -5 when nothing was created at that address, -2 when the component is not created
of_item (string as_keys) → n_pbt_menubar_itemHandle of an item, by its address — of_item("file/export/pdf") —, to read or set its properties. It is exactly what ue_item_selected hands you: the argument goes straight back in here. Never the key alone: two submenus may each hold a pdf, and only the address tells them apart. An address of one level names a menu: its handle changes nothing, use of_menu
of_menu (string as_key) → n_pbt_menubar_menuHandle of a top-level menu, to rename it or grey it out. of_add_menu could only do it at creation: greying Admin when the user logs out meant rebuilding the whole bar; ib_visible takes it out of the bar, entries and shortcuts asleep with it
of_remove_item (string as_keys) → longRemoves one item, at its address (file/open, file/export/pdf) — its cascade with it; the others stay. Its handles are freed and its shortcut disarmed: the key goes back to your application. Without it there was only of_clear, which empties everything — the commonest dynamic menu, a recent files list, meant razing the whole bar on every document opened. Returns 0 once applied, -5 when no item lives at that address, -2 when the component is not created
of_remove_menu (string as_key) → longRemoves a top-level menu, its items with it — handles freed, shortcuts disarmed. The bar is redrawn and its height announced again. Returns 0 once applied, -5 for a menu never added, -2 when the component is not created
of_clear ( )Empties the bar — menus and items; their handles are freed and the shortcuts of the items disarmed. Returns 0 once applied, -2 when the component is not created
of_reset ( )Empties the bar and puts every property back to its default. Returns 0 once applied, -2 when the component is not created
of_set_redraw (boolean)Groups a burst of changes into a single render. Returns 0 once applied, -2 when the component is not created
of_save_as_png (string) · of_save_as_jpg (string)Exports the rendering as an image. Returns 0 once the image is written, -4 when writing fails, -2 when the component is not created

Events #

EventRaised when
ue_menu_opening (string as_key)Raised when a top-level menu is about to open — and the dropdown waits: it opens only once the event has returned. Enable, grey or fill its items here: the change shows in this opening, not the next one. Without it the whole bar had to be kept in step with the application state at all times, or show items that lie
ue_menu_closed (string as_key)The dropdown of a top-level menu closed without a choice: by the user (a click outside, Escape, or sliding to the next menu), or by your code removing, clearing, hiding or greying the open menu (of_remove_menu, of_clear, ib_visible, ib_enabled) — an order raises it too. Undo here what ue_menu_opening prepared (a preview, a selection). A pick raises ue_item_selected instead, and of_reset raises nothing
ue_item_selected (string as_keys)The user picked an item, or pressed its shortcut. as_keys is its address, the menu first — file/open, file/export/pdf: the key alone does not say which submenu it came out of, and two submenus may each hold their own. That same string goes straight back to of_item. An item greyed, hidden or removed while its dropdown was open raises nothing
ue_item_hover (string as_keys)With ib_track_hover = true: the entry under the pointer or the keyboard in an open dropdown, by its address (file/export/pdf) — a greyed entry too, its help can say why. Raised once per entry, then with an empty address when the dropdown closes (before ue_item_selected on a choice): write the help text of a status bar, then empty it
ue_auto_height (long al_height)The bar announces the height it needs — move whatever sits below it
ue_ready ( )The component has finished loading; everything sent before was replayed
ue_runtime_missing ( )The WebView2 runtime is missing: the component stays empty
ue_bg_color (long al_color)The component computed its theme background; the userobject already adopted it (backcolor)

One line, by default. The titles that do not fit go into the chevron at the end of the bar (ib_wrap = false, the default): the height stays that of one line and ue_auto_height is raised once. With ib_wrap = true the bar wraps: it never scrolls, its height follows the rows and ue_auto_height tells you by how much at every change of width.


From the keyboard #

KeyEffect
Alt · F10Hands the keyboard to the bar and underlines the letters of the menus, as in any Windows application; a second press gives it back
»The chevron of the titles that do not fit: the arrows stop on it like on a title, Enter or Down opens the list of the hidden menus, and Alt + the letter of a hidden menu opens that menu from the chevron
Alt + letterOpens the menu of that letter (&File) from any control of the window — a field, a DataWindow. An Alt+letter shortcut your application registered comes first. Two menus on the same letter: the band walks from one to the other, Enter opens. An accented or non-Latin letter is typed as on the keyboard (&Édition: Alt + the key of É)
ArrowsWalk the menus and their items, skipping greyed menus; right opens a sub-item, left goes back up. In right-to-left writing (RTL), everything turns round: on the bar, in the dropdown (aligned on the right edge of its title) and in the cascades, which open to the left — left opens, right goes back up
EnterIn a dropdown: picks the highlighted item (ue_item_selected). On a title of the bar, Enter, Space or Down arrow opens the menu. Space does not pick an item — the Windows rule too
EscapeCloses the open menu, then hands the focus back to the control that had it

A menu bar never keeps the focus. A click on a title, then a pick with the mouse: the keyboard goes back to the control the user was typing in before ue_item_selected is raised. Edit > Paste therefore pastes into the field being edited, and GetFocus() names it in the event.


Examples #

A complete menu bar #

// Freeze the drawing while you build
uo_menus.of_set_redraw(/*on*/ false)

// The File menu, with an icon on Open and a line before Quit
uo_menus.of_add_menu(/*key*/ "file", /*text*/ "&File")
uo_menus.of_add_item(/*keys*/ "file/open", /*text*/ "&Open...", /*image*/ "mono:img\packimages.dll:svg/samples/folder-open", /*checked*/ false)
uo_menus.of_add_separator(/*keys*/ "file")
uo_menus.of_add_item(/*keys*/ "file/quit", /*text*/ "&Quit")

// A submenu: Export, then its two formats
uo_menus.of_add_item(/*keys*/ "file/export", /*text*/ "&Export")
uo_menus.of_add_item(/*keys*/ "file/export/csv", /*text*/ "CSV")
uo_menus.of_add_item(/*keys*/ "file/export/pdf", /*text*/ "PDF")

// The View menu: an option that checks
uo_menus.of_add_menu(/*key*/ "view", /*text*/ "&View")
uo_menus.of_add_item(/*keys*/ "view/grid", /*text*/ "&Grid", /*image*/ "", /*checked*/ true)

// One single redraw, with everything
uo_menus.of_set_redraw(/*on*/ true)

Check, uncheck, grey out #

// The user toggled the grid display
uo_menus.of_item(/*keys*/ "view/grid").ib_checked = not uo_menus.of_item(/*keys*/ "view/grid").ib_checked
// An item that no longer applies is greyed, not removed:
// the user has to be able to see that it exists
uo_menus.of_item(/*keys*/ "file/save").ib_enabled = false

Radio items and a zoom shortcut #

// Two RADIO items: checking one unchecks the other, a round bullet replaces the tick
uo_menus.of_add_item(/*keys*/ "view/small", /*text*/ "&Small icons")
uo_menus.of_add_item(/*keys*/ "view/large", /*text*/ "&Large icons")
uo_menus.of_item(/*keys*/ "view/small").is_group = "size"
uo_menus.of_item(/*keys*/ "view/large").is_group = "size"
uo_menus.of_item(/*keys*/ "view/large").ib_checked = true

// Zoom: Ctrl++ is shown AND armed, wherever the focus is
uo_menus.of_add_item(/*keys*/ "view/zoomin", /*text*/ "Zoom &in")
uo_menus.of_item(/*keys*/ "view/zoomin").is_shortcut = "Ctrl++"

Rebuilding the bar #

// Switching workspace: empty, then fill again
// of_set_redraw avoids repainting on every line
uo_menus.of_set_redraw(/*on*/ false)
uo_menus.of_clear()
uo_menus.of_add_menu(/*key*/ "tools", /*text*/ "&Tools")
uo_menus.of_set_redraw(/*on*/ true)

A narrow bar, Help at the end, a help text in the status bar #

// Help at the end of the bar ; what does not fit goes into the chevron
uo_menubar.of_menu(/*key*/ "help").is_align = u_pbt_menubar.ALIGN_END

// Section headers in View
uo_menubar.of_add_header(/*keys*/ "view", /*text*/ "Panels")
uo_menubar.of_add_item(/*keys*/ "view/tree", /*text*/ "Tree")
uo_menubar.of_add_item(/*keys*/ "view/output", /*text*/ "Output")

// A help text in the status bar for the pointed entry
uo_menubar.ib_track_hover = true

// ue_item_hover (string as_keys) of uo_menubar
choose case as_keys
	case "file/save"
		st_status.Text = "Saves the document"
	case ""
		st_status.Text = ""
end choose

Best practices #

Inherited from the common base #

These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.

MembersRoleDetailed in
of_count · of_keys_at · of_hasWalk what the component holds3.2 Items
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine

Two helpers are not inherited: of_icon and of_escape_markup live on n_pbt_utils. Declare one — n_pbt_utils lnv_utils, nothing to create — and call them on it.


← Component reference · Guide contents