Menu Factory
Several Actipro products include built-in contextual menus. These menus are primarily based on the native menu controls of the WinForms platform, and some controls expose events where these menus can be customized and/or cancelled.
While this approach is effective, it can be burdensome to identify and respond to all the appropriate events just to customize a menu. This is especially true if the WinForms native menu controls need to be replaced by alternate menus (like those used by an application's main menu) since end-users expect all menus in an application to be consistent.
Replacing the Default Menus
All Actipro products will create built-in contextual menus using the menu factory currently assigned to MenuFactory.Current. By default, this value is initialized to a factory object that creates WinForms native menu controls. This default instance is always available from the MenuFactory.Default property.
To change the factory object used by Actipro controls, set the MenuFactory.Current property to an instance of any class that implements the IMenuFactory interface.
Integrating with Actipro Bars
Actipro offers a Bars product, so we have made it easy to configure all Actipro products to use our own product. To change from the WinForms native menus to Bars Popup Menus, simply set MenuFactory.Current to a new instance of BarsMenuFactory.
using ActiproSoftware.UI.WinForms.Controls;
using ActiproSoftware.UI.WinForms.Controls.Bars;
...
public partial class MainForm : Form {
private BarManager _barManager;
public MainForm() {
InitializeComponent();
// Configure BarsMenuFactory using BarManager hosted on the form
MenuFactory.Current = new BarsMenuFactory(_barManager);
...
}
...
}
Integrating with 3rd Party Controls
Any implementation of IMenuFactory requires the base control types to implement the following interfaces:
- IMenu - Defines the base requirements for a contextual menu control.
- IMenuItem - Defines the base requirements for items within a menu.
- IMenuSeparator - Defines the base requirements for separators between menu items.
The easiest way to implement IMenuFactory is to derive from MenuFactory<T,U,V>, where each of the generic type arguments identify the type to be used for menus, menu items, and menu separators. As needed, override the CreateMenuCore, CreateMenuItemCore, and CreateMenuSeparatorCore methods to instantiate and configure each respective control, as needed.
Tip
If you have custom menu-based controls that derive from WinForms native controls, those controls can easily be wrapped in their required IMenu, IMenuItem, and IMenuSeparator interfaces by calling MenuFactory.WrapMenu, MenuFactory.WrapMenuItem, or MenuFactory.WrapMenuSeparator, respectively.
Working with Icons
The built-in MenuFactory<T,U,V> class, and any class that derives from it, provides several options for working with icons.
By default, menu items can support the display of icons if one is available. To force menu items to display without icons, set MenuFactory<T,U,V>.AllowIcons to false.
Command Keys
Built-in contextual menus will request a specific key to be associated with each menu item, and constants are declared which define these keys. When attempting to programatically identify a menu item, it is always recommended to compare it to one of the available constants since the actual values could change over time. The following classes are available for command key constants, with some being specific to their respective assemblies:
ActiproSoftware.Properties.Shared.CommandKeysActiproSoftware.Properties.Docking.CommandKeysActiproSoftware.Properties.Navigation.CommandKeys
Identifying a Menu Item
When using the default menu factory for native controls, the Key will be assigned to ToolStripMenuItem.Name.
When using BarsMenuFactory, the Key will be parsed into separate category and name values based on the format "Category.Name" (e.g., "Edit.Copy"). These values are then assigned to BarCommand.Category and BarCommand.Name, respectively. Then end result is that the value of BarCommand.FullName, a read-only property that combines of the Category and Name properties), will exactly match the original value for Key.
Important
If the Key does not contain exactly one dot (.) separator, BarsMenuFactory will assign a default category of "IMenuFactory" and the name will be the full value of the Key. This default behavior can be modified by creating a new class that derives from BarsMenuFactory and overrides TryParseCommandFullName to generate the desired result.
Using Menu Factory
While the menu factory classes were created to help ensure developers could easily customize the default menus created by Actipro products, there is no reason they cannot be used by anyone wanting a centralized way to manage their contextual menus. The following demonstrates how the current menu factory could be used to create a show a simple context menu:
using ActiproSoftware.Properties.Shared;
...
var menuFactory = MenuFactory.Current;
var menu = menuFactory.CreateMenu();
menu.Items.Add(menuFactory.CreateMenuItem(new MenuFactoryMenuItemOptions() { Key = CommandKeys.Edit.Cut, Text = "Cu&t", Command = MyCommands.Cut } ));
menu.Items.Add(menuFactory.CreateMenuItem(new MenuFactoryMenuItemOptions() { Key = CommandKeys.Edit.Copy, Text = "&Copy", Command = MyCommands.Copy } ));
menu.Items.Add(menuFactory.CreateMenuItem(new MenuFactoryMenuItemOptions() { Key = CommandKeys.Edit.Paste, Text = "&Paste", Command = MyCommands.Paste } ));
menu.Items.Add(menuFactory.CreateMenuSeparator());
menu.Items.Add(menuFactory.CreateMenuItem(new MenuFactoryMenuItemOptions() { Key = CommandKeys.Edit.Delete", Text = "&Delete", Command = MyCommands.Delete } ));
menu.Show(myControl, new Point(x, y));