Windows Forms ToolStrip Abstract This 6 hour course is intended for Microsoft Support Engineers who support and develop Windows Forms applications for Windows® Visual Studio® .NET 2005 and the Microsoft .NET Framework 2.0. Topics highlight capabilities of ToolStrip and its associated classes; describe how to use them to create Windows forms applications that have a Windows XP, Office, Internet Explorer, or custom appearance and behavior. The training also includes handson labs and howto samples.
Objective At the end of this course, you will be able to describe the highlights of Toolstrip capabilities and use them to develop applications that have a Windows XP, Office, Internet Explorer, or custom appearance and behavior in Visual Studio 2005.
Outline · · · · · · ·
Class hierarchies Feature highlights ToolStrip Layout ToolStripContainer Settings Using ToolStrip in MDI applications Rendering or Painting
Overview Creating advanced toolbar functionality with a consistent and professional appearance and behavior is one of the top requested features from Windows Forms developers of all skill levels. To meet such requests, the Windows Forms product group has added the ToolStrip and associated classes in Framework 2.0. What is ToolStrip? The ToolStrip family of controls provides and common interface for producing user interface elements for Windows Forms. The ToolStrip, MenuStrip, ContextMenuStrip, StatusStrip, and ToolStripDropDown controls replace the previous toolbar, main menu, context menu, and status bar controls respectively, although those controls are retained for backward compatibility. In addition to replacing these controls, ToolStrip and its associated controls provide a common rendering model, extensibility options, parallel UI across containers and supporting utility functions and usage controls. Why use ToolStrip?
1
ToolStrip and its associated classes provide many advantages over the old ToolBar, MainMenu, StatusBar and ContextMenu that were shipped in the previous versions of .NET Framework. It provides • Overflow support • Custom layout support • Support controls right in menus and toolbars • Consistent object model • Simpler to mix/match items • Enhanced design time experience
ToolStrip runtime features incorporate a careful blend of agility and utility. You can easily create application elements with a professional look and feel, or use your imagination to create that one ofakind application. Highlights of ToolStrip capabilities: · ToolStrip and derived classes replace the existing ToolBar, MainMenu, StatusBar and ContextMenu classes. In addition, they provide functionality beyond these controls in the previous versions.
2
· · · · · · · ·
ToolStrip control hosted items include ToolStripTextBox, ToolStripComboBox, ToolStripProgressBar ToolStrips can generically host controls via ToolStripControlHostItem Shareable, customizable renderers across all ToolStrips Consistent API across all of ToolStrips with appropriate pattern specializations. Freely positionable ToolStrips with rafting containers Automatic Overflow menu support Automatic end user customization retention via config Opacity, transparency, animated gif and region support
ToolStrip designer has taken the success of the main menu editor to new heights. It offers in place editing of text along with limitless automatic nesting of submenus. Highlights of ToolStrip designer capabilities: · · · · · · · ·
Easily create complex, dynamic shell components interactively Drag and drop to rearrange items Copy/paste between levels or across forms Drag, position and drop ToolStrips, MenuStrips, StatusStrips to form sides in new rafting containers Inplace editing within the automatic Overflow Morph item types to more complex types Oneclick convert a ToolStripButton to a ToolStripDropDownButton while retaining common properties Customized, ultraquick access to common properties on the smart panel
ToolStrip Classes at a Glance Technology Toolbar, Status, and Menu containers
ToolStrip Items
Classes ToolStrip MenuStrip ContextMenuStrip StatusStrip ToolStripDropDown ToolStripOverflow ToolStripDropDownMenu ContextMenuStrip ToolStripButton ToolStripSeparator ToolStripLabel ToolStripStatusLabel ToolStripControlHost ToolStripComboBox ToolStripTextBox ToolStripProgressBar ToolStripDropDownItem ToolStripSplitButton ToolStripMenuItem ToolStripDropDownButton ToolStripOverflowButton
3
Location
ToolStripContainer
Presentation and Rendering
ToolStripManager ToolStripRenderer ToolStripProfessionalRenderer ToolStripSystemRenderer ToolStripRenderMode
Terminologies
Partial Trust The limitations of ToolStrips under partial trust are designed primarily to prevent spoofing attacks. Spoofing attacks consist of some fake dialog or familiar window that lures the user into entering personal information. The two elements are a full fidelity window AND key entry. ToolStrip, because of the flexibility in rendering, protects only the key entry half of this attack. We do this via a combination of protections: In ToolStripDropDowns, we require UIPermission.AllWindowsPermission to display ControlHostItems. This applies to both intrinsic (ToolStripTextBox, ToolStripComboBox,
4
ToolStripProgressBar) and user created. Rather than throw, we simply do not display these items where the requirement is not met. We disallow AutoClose == false and ignore the cancelable closing event param. This makes it impossible to enter more than one keystroke and not cause dropdown dismissal. Like above, we would not throw, but simply ignore the value. We restrict keystroke handling events. Many keyboard related events will not be raised if in partial trust contexts less than UIPermission.AllWindowsPermission. Mnemonics are not processed when UIPermission.AllWindowsPermission is not granted. This is done to prevent a keystroke sniffing attack where a ContextMenuStrip that contains an item for each letter could be reshown again and again. Each time it was dismissed one more letter would be captured.
Usage Toolstrips have three main usage patterns that impact how they are laid out, keyboard interaction and enduser behavior. Joined in a ToolStripPanel This means that the ToolStrip is typically repositionable within the ToolStripPanel and across ToolStripPanels. The dock property is ignored, and the size of the ToolStrip if not Stretch grows with more items. It usually does not participate in Tab order. Docked The ToolStrip is docked to one side of a container, is in a fixed position and size expanding over the entire edge to which it is docked. It usually does not participate in Tab order. Absolutely Positioned This mode is using the ToolStrip just like a control. It is placed via the location property, has a fixed size and typically participates in the Tab order. Keyboarding Mnemonics Combined with or following the ALT key, mnemonics are one way to activate a ToolStripItem via keyboard. ToolStrip supports both explicit and implicit mnemonics. Explicit mnemonics are defined inline with the ampersand (&) character preceding the letter. Implicit mnemonics are determined by an algorithm within ToolStrips that attempts to find a matching item based on order of characters in the Text property. Shortcuts Shortcuts used by MenuStrips are different from ShortcutKeys used in MainMenu. One is a pre combined list of key combinations. MenuStrips simply use combinations of the Keys enumerations (not order specific) to define the shortcut. In addition a provision is made to display a shortcut key via text (e.g. Delete vs. Del) via the ShortcutDisplayString.
5
Navigation Pressing the Alt key activates the MenuStrip pointed to by Form.MainMenuStrip. From there, pressing CTRL+TAB navigates between ToolStrips within ToolStripPanels. TAB and arrow keys are used to navigate between items in a ToolStrip. The ToolStrip classes use a special nearest item arrow handling algorithm in the Overflow to handle cross row navigation. Spacebar clicks ToolStripButton, ToolStripDropDownButton, ToolStripSplitButton. Focus/Validation For the most part, when activated by the menu key (ALT), the MenuStrip/ToolStrip will try not to take focus away from the control that is currently focus. If there is a control hosted within the MenuStrip or a dropdown of the MenuStrip, the Control will gain focus when tabbed to. In general, the GotFocus/LostFocus/Enter/Leave events on MenuStrip may not fire when keyboard activated. In such cases, the MenuStrip.MenuActivate, MenuStrip.MenuDeactivate events can be used instead. By default ToolStrip.CausesValidation is False. Validation can be performed by manually calling Validate() on the Form. How can I tab out of a ToolStrip? It just starts over from the first item again and again. In this case, the ToolStrip will accept the first tab to tab in and the arrow keys will do wrapping selection. The second tab will tab you to the next control. Commonly used when not contained within a ToolStripPanel: toolStrip.TabStop = true;
Class Hierarchies This section describes the class hierarchies of the ToolStrip and its associated classes.
ToolStrip class This shows the inheritance hierarchy of the ToolStip class: System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.ScrollableControl System.Windows.Forms.ToolStrip System.Windows.Forms.BindingNavigator System.Windows.Forms.MenuStrip System.Windows.Forms.StatusStrip System.Windows.Forms.ToolStripDropDown System.Windows.Forms.ToolStripOverflow System.Windows.Forms.ToolStripDropDownMenu System.Windows.Forms.ContextMenuStrip
6
ToolStrip (Replacement for ToolBar)
MenuStrip
StatusStrip
(Replacement for MainMenu)
(Replacement for StatusBar)
ToolStripDropDown
ToolStripDropDownMenu
BindingNavigator
ToolStripOverflow
ContextMenuStrip (Replacement for ContextMenu)
Note: Although ToolStrip, MenuStrip, StatusStrip and ContextMenuStrip controls replace the ToolBar, MainMenu, StatusBar and ContextMenu controls of previous versions, ToolBar, MainMenu, StatusBar and ContextMenu are retained for both backward compatibility and future use if you choose. By default, they will not show up in the ToolBox. The users will need to manually add them to the ToolBox or use them programmatically. We will not discuss the BindingNavigator class since it has been covered in the “Windows Forms DataGridView and DataBinding in .NET Framework 2.0” course. This course will focus on the MenuStrip, StatusStrip and ToolStripDropDown classes in the ToolStrip family.
ToolStripItem class A ToolStripItem is an abstract class that derives from System.ComponentModel.Component and it is the base class for all the items that go into a ToolStrip. There are several different kinds of ToolStripItems such as a button, combo box, text box, or label that can be contained in a ToolStrip control or a ToolStripDropDown control. While the ToolStrip
7
class manages the painting and keyboard and mouse input (including draganddrop input) for these elements, the ToolStripItem class manages events and layout. ToolStripItem is not a control. This is for performance reasons. It is a lightweight solution to get around the window handle limitation on some OS (e.g, there's a limit of 16,364 window handles on Windows 95/98/Me). Therefore, items derived from ToolStripItem do not have handles. The following shows the inheritance hierarchy of the ToolStripItem class. System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.ToolStripItem System.Windows.Forms.ToolStripButton System.Windows.Forms.ToolStripLabel System.Windows.Forms.ToolStripStatusLabel System.Windows.Forms.ToolStripSeparator System.Windows.Forms.ToolStripControlHost System.Windows.Forms.ToolStripTextBox System.Windows.Forms.ToolStripComboBox System.Windows.Forms.ToolStripProgressBar System.Windows.Forms.ToolStripDropDownItem System.Windows.Forms.ToolStripMenuItem System.Windows.Forms.ToolStripSplitButton System.Windows.Forms.ToolStripDropDownButton System.Windows.Forms.ToolStripOverflowButton
The following chart describes elements that derive from the ToolStripItem class. These elements do not have window handles and they can be hosted in a ToolStrip or ToolStripDropDown.
8
ToolStripItem (Abstract class)
ToolStripButton
ToolStripLabel
ToolStripControlHost
ToolStripDropDownItem (Abstract class)
ToolStripSeparator
ToolStripStatusLabel
ToolStripTextBoxt
ToolStripMenuItem
ToolStripComboBox
ToolStripSplitButton
ToolStripDropDownButton
ToolStripProgressBar
ToolStripOverflowButton
ToolStripManager class This class inherits from System.Object and it cannot be inherited. You can use it to join ToolStrip controls within a specified ToolStripContainer and merge ToolStrip controls with each other. You can use it to control the arrangement, painting, and display style of ToolStrip. The overloaded Merge method combines ToolStrip controls with each other, and the overloaded RevertMerge method undoes a merge operation. You can use it together with the ToolStripRenderer class to gain even more control and customizability over painting and layout style. You can also use it together with the ToolStripControlHost class to host any other Windows Forms control in a ToolStrip,
9
Feature highlights This section highlights some of the important features in ToolStrip and its associated classes.
ToolStrip class This section contains information relevant to ToolStrip as a base class and ToolStrip as a control. ToolStrip is not only replacement for ToolBar, but also the base class for MenuStrip, StatusStrip and ContextMenuStrip. By default it uses the SplitStackLayout which supports two virtual stacks of items. The enables support of overflow and alignment within the ToolStrip.
The following table lists some of the important members of the ToolStrip class. Property Names
Description
AllowItemReorder
Setting this value to True allows the items on the ToolStrip to be reordered at run time while the Alt key is pressed. By default, the value is set to False. When you set it to True, the user can hold down the ALT key and the left mouse button to drag a ToolStripItem to a different location on the ToolStrip at run time.
AllowMerge
Setting this value to true (default) allows multiple MenuStrip, ToolStripDropDownMenu, ToolStripMenuItem, and other types to be combined. You can use this property to enable MDI children to combine their respective menus in the MDI parent.
CanOverflow
Indicates whether items in the ToolStrip can overflow. Overflow means that when you shrink the window, there will be a dropdown arrow at the end of the ToolStrip which you can click to display the items that do not fit on the ToolStrip any more. When this property
10
is set to false, the dropdown arrow does not show up to display the items that no longer fit on the ToolStrip. A ToolStripItem is not displayed if it is clipped. CanOverflow set to true:
CanOverflow set to false:
DefaultDropDownDirection Indicates the default direction in which a ToolStripDropDown control is displayed relative to the ToolStrip. This property can only be set at run time. For example, when you set it to ToolStripDropDownDirection.AboveLeft, you get the following look at run time:
GripDisplayStyle
Read only property. Indicates whether ToolStrip grip or move handle is horizontal or vertical.
GripMargin
Use this property to manipulate the space around the ToolStrip move handle. Because System.Windows.Forms.Padding can take individual values for Top, Bottom, Left, and Right, you can adjust the space around the move handle as desired. The margin can even be off the edge of the ToolStrip.
GripRectangle
Gets the boundaries of the ToolStrip move handle. You can use this property to get boundaries for painting, hit testing, and so on.
GripStyle
Controls the visibility of the ToolStrip grip or move handle.
ImageScaling
This is the size that will be used to scale into as determined by the
11
Item’s ImageScaling and the container’s AutoSize setting. LayoutStyle
Specifies the layout orientation of ToolStrip. For example, you get the following look when the LayoutStyle is set to Table.
OverflowButton
Gets the ToolStripItem that is the overflow button for a ToolStrip with overflow enabled.
Renderer
Gets or sets a ToolStripRenderer used to customize the look and feel of a ToolStrip.
RenderMode
Controls the painting styles to be applied to the ToolStrip. When it is set to System, it provides the look and feel of IE; when it is set to Professional, it provides the look and feel of Office. When it is set to ManagerRenderMode, then the painting style is determined by how the ToolStripManager renders. Using System render mode:
Using Professional render mode:
ShowItemToolsTips
Indicates whether ToolTips are to be displayed on ToolStrip items. The default value is set to True. Set it to False if you do not want ToolTips to display.
Stretch
Gets or sets a value indicating whether the ToolStrip stretches from end to end in the ToolStripContainer. When a ToolStrip is contained within a ToolStripPanel (so that it can be moved by the user of the application), it can either fill an entire row of the ToolStripPanel or size to the ToolStrip’s contents. The ToolStrip.Stretch property controls this behavior: · Stretch = True, the ToolStrip fills the entire row; · Stetch = False, the ToolStrip sizes as normal;
12
TextDirection
Specifics the direction to draw text on a ToolStrip. For example, when you set it to Vertical90, you get the following look:
Method Names
Description
OnLayoutCompleted
Raises the LayoutCompleted event.
OnLayoutStyleChanged
Raises the LayoutStyleChanged event. You can override this method or handle the LayoutStyleChanged event to customize the ToolStrip’s appearance when the layout style changes. For example, you can make the ToolStrip items to have vertical text when you dock it to the side of the Form by handling the LayoutStyleChanged event:
OnPaintGrip
Raises the PaintGrip event.
OnRendererChanged
Raises the RendererChanged event. You can override this method or handle the RendererChanged event to provide more control over the painting style of the ToolStrip when you change the ToolStrip’s Renderer property.
Event Names
Description
LayoutCompleted
Occurs when the layout of the ToolStrip is complete.
LayoutStyleChanged
Occurs when the value of the LayoutStyle property changes. See OnLayoutStyleChanged.
PaintGrip
Occurs when the ToolStrip move handle is painted.
RendererChanged
Occurs when the value of the Renderer property changes.
MenuStrip class
13
MenuStrip is the ToolStrip family of control’s replacement for MainMenu. It also handles the majority of key handling in the menu activation case and has special logic around Form.MainMenuStrip. The MenuStrip control supports the multipledocument interface (MDI) and menu merging, tool tips, and overflow. You can enhance the usability and readability of your menus by adding access keys, shortcut keys, check marks, images, and separator bars. The MenuStrip control replaces and adds functionality to the MainMenu control; however, the MainMenu control is retained for backward compatibility and future use if you choose.
The following table lists some of the important members of the MenuStrip class. Property Names
Description
AllowItemReorder
Setting this value to true allows the items on the MenuStrip to be reordered at run time while the Alt key is pressed.
AllowMerge
Setting this value to true (default) allows multiple menu items to be merged.
CanOverflow
Indicates whether the MenuStrip supports overflow functionality.
LayoutStyle
Specifies the layout orientation of MenuStrip. For example, you get the following look when the LayoutStyle is set to VerticalStackWithOverflow:
14
MdiWindowListItem
Gets or sets the ToolStripMenuItem that is used to display a list of MDI child forms.
RenderMode
Controls the painting styles to be applied to the MenuStrip. When it is set to System, it provides the look and feel of IE; When it is set to Professional, it provides the look and feel of Office. When it is set to ManagerRenderMode, then the painting style is determined by how the ToolStripManager renders. Using System render mode:
Using Professional render mode:
ShowItemToolsTips
The default value of this property for MenuStrip is False.
Stretch
Specifics whether the MenuStrip stretches from end to end in the rafting container.
TextDirection
Specifics the direction to draw text on a MenuStrip. For example, when you set it to Vertical270, you get the following look:
15
StatusStrip class A StatusStrip control displays information about an object being viewed on a Form, the object's components, or contextual information that relates to that object's operation within your application. Typically, a StatusStrip control consists of ToolStripStatusLabel objects, each of which displays text, an icon, or both. The StatusStrip can also contain ToolStripDropDownButton, ToolStripSplitButton, and ToolStripProgressBar controls. The default StatusStrip has no panels. To add panels to a StatusStrip, use the ToolStripItemCollection.AddRange(System.Windows.Forms.ToolStripItem[]) method. Although StatusStrip replaces and extends the StatusBar control of previous versions, StatusBar is retained for both backward compatibility and future use if you choose.
The following table lists some of the important members of the StatusStrip class. Property Names
Description
CanOverflow
Indicates whether the StatusStrip supports overflow functionality.
LayoutStyle
Specifies the layout orientation of StatusStrip. For example, you get the following look when the LayoutStyle is set to Table:
RenderMode
Controls the painting styles to be applied to the StatusStrip. When it is set to System, it provides the look and feel of IE; when it is set to Professional, it provides the look and feel of Office. When it is set to ManagerRenderMode, then the painting style is determined by how the ToolStripManager renders.
16
ShowItemToolTips
The default value of this property for StatusStrip is False.
Stretch
Specifics whether the StatusStrip stretches from end to end in the rafting container.
Layout of the StatusStrip One note about layout in the StatusStrip is that certain properties on the LayoutSettings object will be overwritten in the case of laying out ToolStripStatusLabels with Spring = True.
Grip and SizingGrip There are two different grips on StatusStrip: 1. Grip: This is the element of the StatusStrip which provides the user a drag starting point to reposition the StatusStrip between ToolStripPanels. It is rendered vertically at the start of the StatusStrip. 2. SizingGrip: SizingGrip is the element that provides a way to resize the form in whch the StatusStrip is docked. It is rendered as diagonal shadowed lines at the bottom end of the StatusStrip.
How can I get an item aligned to the right on the StatusStrip? By default, the StatusStrip is not set to LayoutStyle.StackWithOverfow, therefore the item.Alignment property is ignored. To align a progress bar to the right, use a ToolStripStatusLabel by setting its Spring property to True, then adding a ToolStripProgressBar to it. The ToolStripStatusLabel’s Text property can be set to “” to remove the text.
17
ToolStripDropDown class ToolStripDropDown
ToolStripDropDownMenu
ToolStripOverflow
ContextMenuStrip
A ToolStripDropDown represents a control that allows the user to select a single item from a list that is displayed when the user clicks a ToolStripDropDownButton or a ToolStripDropDownSplitButton. For instance, you can use the ToolStripDropDown to display dropdown lists of options, such as a color picker. Although ToolStripDropDownMenu and ToolStripDropDown replace and add functionality to the Menu control of previous versions, Menu is retained for both backward compatibility and future use if you choose.
18
The following table lists some of the important properties of the ToolStripDropDown class. Property Names
Description
AutoClose
Indicates whether the ToolStripDropDown control should automatically close when it has lost activation.
CanOverflow
Indicates whether the items in a ToolStripDropDown can be sent to an overflow menu.
OwnerItem
OwnerItem is used to access the item which sourced the dropdown. This is analogous to ContextMenuStrip.SourceControl, but instead of returning Control it returns ToolStripItem. Note: The concept of container ownership and parenting is more complex in ToolStrips than in a typical Windows Forms container control. That is necessary to support dynamic scenarios such as overflow, sharing drop downs across multiple ToolStrip items and to support spawning ContextMenuStrips from controls.
TopLevel
Gets or sets a value indicating whether the ToolStripDropDown is a toplevel control.
Flow from parent to auto created dropdowns For the implementation of fauxambient properties we make a distinction in how the dropdown for a ToolStripDropDownItem is created. We automatically flow Font, ImageScalingSize and Renderer to the autocreated dropdown. In the case of explicitly created dropdowns, you must set these properties yourself. Explicit creation of ToolStripDropDown This refers to instancing a ToolStripDropDown, ToolStripDropDownMenu or ContextMenuStrip, populating it, and then assigning to a ToolStripDropDownItem’s DropDown property; Implicit (automatic) creation of ToolStripDropDown This refers to populating a ToolStripDropDownItem’s DropDownItems collection. When that item is activated, the dropdown is created by using the item from the OwnerItem’s DropDownItems collection; Sample Run the following sample. It shows the font flows into the veggies menu dropdown, but not fruit. // explicit ContextMenuStrip cms = new ContextMenuStrip(); cms.Items.Add("Apples"); cms.Items.Add("Bananas"); cms.Items.Add("Cherries"); ToolStripMenuItem fruitMenuItem = new ToolStripMenuItem("Fruit"); fruitMenuItem.DropDown = cms; // implicit (automatic) ToolStripMenuItem veggiesMenuItem = new ToolStripMenuItem("Veggies");
19
veggiesMenuItem.DropDownItems.Add("Asparagus"); veggiesMenuItem.DropDownItems.Add("Bok Choy"); veggiesMenuItem.DropDownItems.Add("Cauliflower"); // menustrip MenuStrip ms = new MenuStrip(); // set Font to show property flow ms.Font = new Font("Trebuchet MS", 14, FontStyle.Bold); ms.Items.Add(fruitMenuItem); ms.Items.Add(veggiesMenuItem); this.Controls.Add(ms);
ToolStripOverflow class This class inherits from ToolStripDropDown class and manages the overflow behavior of a ToolStrip. The following table lists some of the important properties. Property Names
Description
Items
Gets all of the items on the ToolStrip, whether they are currently being displayed or not.
LayoutSettings
Controls layout scheme characteristics.
LayoutStyle
Indicates how the ToolStrip lays out the items collection.
OwnerItem
Controls the ToolStripItem that is the owner of this ToolStripOverflow.
ToolStripDropDownMenu class ToolStripDropDownMenu inherits from ToolStripDropDown, and is the base class for ContextMenuStrip. Although ToolStripDropDownMenu and ToolStripDropDown replace and add functionality to the Menu control of previous versions, Menu is retained for both backward compatibility and future use if you choose. The properties of this class that you will probably use directly are the ShowCheckMargin and ShowImageMargin properties, which determine whether the shortcut menu will be able to display a check mark, an image, or both. The following table includes some of the important properties. Property Names
Description
ShowCheckMargin
Indicates whether space for a check mark is shown on the left edge of the ToolStripMenuItem.
ShowImageMargin
Indicates whether space for an image is shown on the left edge of the ToolStripMenuItem.
For example, you will have a menu looking like the following using these two properties:
20
ContextMenuStrip class The ContextMenuStrip class inherits from ToolStripDropDownMenu class. It represents shortcut menus that are displayed when the user clicks the right mouse button over a control or area of the form. Shortcut menus are typically used to combine different menu items from a MenuStrip of a form that are useful for the user given the context of the application. Typically, a shortcut menu is displayed when a user clicks the right mouse button over a control or the form itself. Many visible controls, as well as the Form itself, have a Control.ContextMenuStrip property that binds the ContextMenuStrip class to the control that displays the shortcut menu. More than one control can use a ContextMenuStrip. For example, the following code snippet sets the Form’s ContextMenuStrip and a button’s ContextMenuStrip properties to the same ContextMenuStrip called fruitContextMenuStrip, and it also writes a ToolStripDropDownButton’s DropDown to the fruitContextMenuStrip.
//Assign the ContextMenuStrip to the form's ContextMenuStrip //property. this.ContextMenuStrip = fruitContextMenuStrip; //Add a button to the form and assign its ContextMenuStrip. Button b = new Button(); b.Location = new System.Drawing.Point(60, 160); this.Controls.Add(b); b.ContextMenuStrip = fruitContextMenuStrip; // new ToolStrip ToolStrip ts = new ToolStrip(); ToolStripDropDownButton fruitToolStripDropDownButton = new ToolStripDropDownButton("Fruit", null, null, "Fruit"); ts.Items.Add(fruitToolStripDropDownButton); ts.Dock = DockStyle.Top; // wire up DropDownItem DropDown fruitToolStripDropDownButton.DropDown = fruitContextMenuStrip;
Like its base class ToolStripDropDownMenu, you can use ShowCheckMargin and ShowImageMargin properties to determine whether the shortcut menu will be able to display a check mark, an image, or both. Although ContextMenuStrip replaces and adds functionality to the ContextMenu control of previous versions, ContextMenu is retained for both backward compatibility and future use if so desired.
21
The following table lists some of the important properties: Property Names
Description
ShowCheckMargin
Indicates whether space for a check mark is shown on the left edge of the ToolStripMenuItem.
ShowImageMargin
Indicates whether space for an image is shown on the left edge of the ToolStripMenuItem.
SourceControl
Identical in function to the old ContextMenu’s SourceControl. It is used to determine which control sourced the ContextMenuStrip when multiple controls share the same ContextMenuStrip. Note: The concept of container ownership and parenting is more complex in ToolStrips than in a typical Windows Forms container control. That is necessary to support dynamic scenarios such as overflow, sharing drop downs across multiple ToolStrip items and to support spawning ContextMenuStrips from controls.
How do I prevent a dropdown from closing? There are two ways: · Set AutoClose = False; · Handle the Closing event and set e.Cancel = True; If you want to prevent the dropdown from being closed when a specific item is clicked sync the Opening event, hold onto that item, and when the Closing event comes (and the e.CloseReason is ItemClicked), cancel the event. How can I control closing so that clicking on one item is required? This sample covers dynamically adding items, showing the dropdown and how to implement a close item that is required to dismiss the dropdown. public partial class Form1 : Form { ContextMenuStrip MyContextMenuStrip = new ContextMenuStrip(); bool CloseClicked = false; public Form1() { InitializeComponent(); // add close item, name it MyContextMenuStrip.Items.Add("Close"); // add separator MyContextMenuStrip.Items.Add(""); // handle MouseDown to no reshow context menu strip this.MouseDown += new MouseEventHandler(Form1_MouseDown); // we will add items here MyContextMenuStrip.Opening += new CancelEventHandler(cms_Opening); // we will control closing here
22
MyContextMenuStrip.Closing += new ToolStripDropDownClosingEventHandler(cms_Closing); // we will stash a flag on what item is clicked here MyContextMenuStrip.ItemClicked += new ToolStripItemClickedEventHandler(cms_ItemClicked); } void cms_ItemClicked(object sender, ToolStripItemClickedEventArgs e) { if (e.ClickedItem.Text == "Close") { CloseClicked = true; } } void cms_Opening(object sender, CancelEventArgs e) { // The opening event is automatically cancelled if there are no items to display. // To dynamically populate a dropdown in the Opening event, make sure to set // e.Cancel = false. In this case, we always have an item. // // Add a timestamped item MyContextMenuStrip.Items.Add(DateTime.Now.ToString()); // reset flag CloseClicked = false; } void cms_Closing(object sender, ToolStripDropDownClosingEventArgs e) { e.Cancel = true; // only close if the close item is chosen if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked && CloseClicked) { e.Cancel = false; } } private void Form1_MouseDown(object sender, MouseEventArgs e) { // show on right click if (e.Button == MouseButtons.Right) { // only if not already showing if (!MyContextMenuStrip.Visible) { // coordinates relative to form MyContextMenuStrip.Show(this, e.Location); } } } }
23
How do I use the ImageMargin and CheckMargin properties? class Form5 : Form { // check/image/checkmargin/imagemargin combinectrics public Form5() { // size form to show three wide menuitems this.Width = 500; this.Text = "ToolStripContextMenuStrip: Image and Check Margins"; // new MenuStrip MenuStrip ms = new MenuStrip(); ToolStripMenuItem bothMargins = new ToolStripMenuItem("BothMargins"); ToolStripMenuItem imageMarginOnly = new ToolStripMenuItem("ImageMargin"); ToolStripMenuItem checkMarginOnly = new ToolStripMenuItem("CheckMargin"); ToolStripMenuItem noMargins = new ToolStripMenuItem("NoMargins"); // wire DropDowns, customize // both bothMargins.DropDown = CreateCheckImageContextMenuStrip(); ((ContextMenuStrip)bothMargins.DropDown).ShowImageMargin = true; ((ContextMenuStrip)bothMargins.DropDown).ShowCheckMargin = true; // Image only imageMarginOnly.DropDown = CreateCheckImageContextMenuStrip(); ((ContextMenuStrip)imageMarginOnly.DropDown).ShowImageMargin = true; ((ContextMenuStrip)imageMarginOnly.DropDown).ShowCheckMargin = false; // Check only checkMarginOnly.DropDown = CreateCheckImageContextMenuStrip(); ((ContextMenuStrip)checkMarginOnly.DropDown).ShowImageMargin = false; ((ContextMenuStrip)checkMarginOnly.DropDown).ShowCheckMargin = true; // None noMargins.DropDown = CreateCheckImageContextMenuStrip(); ((ContextMenuStrip)noMargins.DropDown).ShowImageMargin = false; ((ContextMenuStrip)noMargins.DropDown).ShowCheckMargin = false; // add items to menustrip ms.Items.Add(bothMargins); ms.Items.Add(imageMarginOnly); ms.Items.Add(checkMarginOnly); ms.Items.Add(noMargins); // dock to top ms.Dock = DockStyle.Top; // add menustrip to the controls collection last Z order! this.Controls.Add(ms); } internal Bitmap CreateSampleBitmap() { // smiley face Bitmap sampleBitmap = new Bitmap(32, 32); Graphics g = Graphics.FromImage(sampleBitmap); using (Pen p = new Pen(ProfessionalColors.ButtonPressedBorder)) { p.Width = 4;
24
Point[] curvePoints = new Point[]{ new Point(4,14), new Point(16,24), new Point(28,14)}; // mouth g.DrawCurve(p, curvePoints); // eyes g.DrawEllipse(p, new Rectangle(new Point(7, 4), new Size(3, 3))); g.DrawEllipse(p, new Rectangle(new Point(22, 4), new Size(3, 3))); } return sampleBitmap; } internal ContextMenuStrip CreateCheckImageContextMenuStrip() { // new ContextMenuStrip ContextMenuStrip checkImageContextMenuStrip = new ContextMenuStrip(); ToolStripMenuItem yesCheckYesImage = new ToolStripMenuItem("Check, Image"); yesCheckYesImage.Checked = true; yesCheckYesImage.Image = CreateSampleBitmap(); ToolStripMenuItem noCheckYesImage = new ToolStripMenuItem("No Check, Image"); noCheckYesImage.Checked = false; noCheckYesImage.Image = CreateSampleBitmap(); ToolStripMenuItem yesCheckNoImage = new ToolStripMenuItem("Check, No Image"); yesCheckNoImage.Checked = true; ToolStripMenuItem noCheckNoImage = new ToolStripMenuItem("No Check, No Image"); noCheckNoImage.Checked = false; // add items to context menu strip checkImageContextMenuStrip.Items.Add(yesCheckYesImage); checkImageContextMenuStrip.Items.Add(noCheckYesImage); checkImageContextMenuStrip.Items.Add(yesCheckNoImage); checkImageContextMenuStrip.Items.Add(noCheckNoImage); return checkImageContextMenuStrip; } }
How can I make a user resizable dropdown? You need to handle WM_NCHITTEST.
ToolStripItem class ToolStripItem is the abstract base class for all the items that go into a ToolStrip. The functionality here is quite extensive. Notable is core eventing, Text, Image, sizing, TextImageRelation, DisplayStyle, Alignment, Owner.
25
The following table shows the elements that derive from the ToolStripItem class and which therefore can be hosted in a ToolStrip or ToolStripDropDown.
Group
Element
Description
Simple elements
ToolStripButton
A toolbar button that supports images and text.
ToolStripLabel
A text label typically used in a status bar or ToolStrip as a comment or title.
└ToolStripStatusLabel A panel in a StatusStrip control.
ToolStripControlHost
ToolStripSeparator
A nonselectable space or space with a horizontal or vertical bar that visually groups elements.
ToolStripComboBox
The user can select text from the dropdown to fill the text box or enter text into the text box.
ToolStripTextBox
Enables the user to enter text.
ToolStripProgressBar
A Wndows progress bar control contained in a StatusStrip.
ToolStripDropDownItem ToolStripDropDownButton
A button that supports dropdown functionality.
└ToolStripOverflowButton Hosts a ToolStripDropDown that displays items that overflow the ToolStrip. ToolStripSplitButton
A combination of a regular button and a dropdown button.
ToolStripMenuItem
A selectable option displayed on a menu or context menu.
26
27
The following table lists some important members of the ToolStripItem class: Property Names
Description
AutoSize
Controls whether the item is automatically sized. By default, it is set to True. To manually set the size of a ToolStripItem, you need to set this property to False and set its Size property to desired size.
Available
Indicates whether the ToolStripItem should be placed on a ToolStrip. See “Available vs. Visible” for further details.
DisplayStyle
Controls whether text and images are displayed on a ToolStripItem. The value can be set to Image, ImageAndText, None, and Text. The default is ImageAndText.
Image
Specifies the image that is displayed on a ToolStripItem. Images in ToolStrips are supported via direct property set or via ImageList support (runtime only). It also supports animated images and .ICO files. The ToolStripItem class supports the ImageAnimator class. When you assign an animated GIF to the Image property, it will automatically render the animation.
ImageAlign
The alignment of the image on a ToolStripItem. The value can be set to any combination of top, middle, and bottom with left, center, and right. The default is MiddleLeft. For example, here is a ToolStripSplitButton with its ImageAlign set to TopLeft and TextAlign set to BottomRight:
ImageIndex
The index value of the image that is displayed on the item.
ImageKey
The key accessor for the image in the ImageList that is displayed on a ToolStripItem.
ImageScaling
This controls whether the image associated with this item is scaled into the size prescribed (either by the ToolStrip.ImageScalingSize or as determined by AutoSize). Note: See the ToolStripItem.ImageScaling table for details.
ImageTransparentColor
The color to treat as transparent in a ToolStripItem image.
Margin
Specifies the space between the item and adjacent items items in this order: Left, Top, Right, and Bottom; You can insert the desired values (in pixels) into the Margin
28
property of the associated control. See “What are padding and margin?” for more details about margin.
MergeAction
How child menus are merged with parent menus. This will be discussed in further details later in the training.
MergeIndex
The position of a merged item within the current ToolStrip.
Overflow
Determines whether the item is attached to the ToolStrip or ToolStripOverflowButton or can float between the two. · AsNeeded : a ToolStripItem drifts between the main ToolStrip and the overflow ToolStrip as required if space is not available on the main ToolStrip; · Always: a ToolStripItem is permanently shown in the overflow ToolStrip; · Never : a ToolStripItem is never a candidate for the overflow ToolStrip. If the ToolStripItem cannot fit on the main ToolStrip, it will not be shown.
Owner
The owner of the item. This returns the ToolStrip whose Items collection contains this ToolStripItem. This is the best way to reference ImageList or other properties in the top level ToolStrip without writing special case code to handle overflow. Note: The concept of container ownership and parenting is more complex in ToolStrips than in a typical Windows Forms container control. That is necessary to support dynamic scenarios such as overflow, sharing drop downs across multiple ToolStrip items and to support spawning ContextMenuStrips from controls.
Padding
Specifies the internal spacing (in pixels) between the item's contents and its edges; See “What are padding and margin?” for more details about padding.
Parent
The parent container of the item. The parent ToolStrip can be distinct from the owner ToolStrip, because the item can fall
29
into another window such as an Overflow. In this case, the Overflow is the parent, but the original ToolStrip is the owner. The parent ToolStrip fires paint events and so on, while the owner ToolStrip contains shared data such as image lists. Typically, the Parent property is set by the layout manager on the ToolStrip. Placement
Specifies where a ToolStripItem is to be layed out: · Main: on the main ToolStrip. · None: not to be layed out on the screen; · Overflow: on the Overflow ToolStrip;
Pressed
Indicates whether the state of the item is pressed.
RightToLeftAutoMirrorImages
Mirrors automatically the ToolStripItem image when the RightToLeft property is set to Yes.
Selected
Indicates whether the item is selected.
TextImageRelation
Controls the position of ToolStripItem text and image relative to each other. The value can be set to ImageAboveText, ImageBeforeText, Overlay, TextAboveImage, and TextBeforeImage. The default is ImageBeforeText. For example, the New button has its TextImageRelation set to ImageAboveText.
TextAlign
The alignment of the text on a ToolStripItem. The value can be set t o any combination of top, middle, and bottom with left, center, and right. The default is MiddleCenter. For example, here is a ToolStripSplitButton with its ImageAlign set to TopLeft and TextAlign set to BottomRight:
Visible
Indicates whether the item is displayed. See “Available vs. Visible” for further details.
Method Name
Description
GetCurrentParent
Rather than expose r/w Parent, the ToolStripItem class provides a read only accessor to the property via this method. Parent differs from Owner in that it will return the current ToolStrip in which the item is displayed within which may be
30
the Overflow. Note: The concept of container ownership and parenting is more complex in ToolStrips than in a typical Windows Forms container control. That is necessary to support dynamic scenarios such as overflow, sharing drop downs across multiple ToolStrip items and to support spawning ContextMenuStrips from controls.
ToolStripItem.ImageScaling ToolStrip AutoSize
ToolStripItem.ImageScalingMode SizeToFit
TRUE
Scales to ToolStrip.ImageScalingSize
(Default) No Image Scaling. ToolStrip sizes to largest of largest item or minimum size
FALSE
Scales to area remaining in ToolStrip
No Image Scaling; No ToolStrip Sizing;
None
What are padding and margin? Padding is the interior space to add, Margin is the exterior space between controls. When a control is a container of items, padding represents the space from the edge of the container.
31
Available vs. Visible In ToolStrips, Visible always returns the true state of the item and its container. That means if you check the visible property of the ToolStripMenuItem before it is ever shown – it will be visible false. Available is what you’d want to use in that case which means it will try to lay that item out. This is regardless of whether it’ll end up in the overflow or Placement = none. If you are using DataBinding, Available is better to bind to than the Visible property, as the Visible property also returns the state of its container. In the case of a ToolStripDropDown, an item is usually going to be Visible = False, but Available = True. How can I get one image out of many to not be scaled? Use ToolStripItem.ImageScaling = ToolStrimItemImageScaling.None How can I tell when the mouse is over a ToolStripItem such as a ToolStripButton? Use the Selected property for items in which "CanSelect" is true. Otherwise you'll have to sync MouseEnter, MouseLeave events. You can check for Selected in your custom Renderer as well.
32
ToolStripButton class This class inherits from ToolStripItem class. It is the button item for ToolStrips. You can use it to create a toolbar button that supports both text and images. Use the ImageAlign and TextAlign properties to get or set the positioning of ToolStripButton images and text. Although ToolStripButton replaces and extends the ToolBarButton control of previous versions, ToolBarButton is retained for both backward compatibility and future use. The following table describes some of the important properties. Property Names
Description
AutoToolTip
Indicates whether default or custom ToolTip text is displayed on the ToolStripButton. By default, the value is set to True, and a ToolStripButton uses its Text property for the ToolTip text. To display custom text via the ToolTipText property, you need to set the AutoToolTip property to False. AutoToolTip is set to true for these classes only • ToolStripButton • ToolStripDropDownButton • ToolStripSplitButton
CanSelect
Whether the ToolStripButton can be selected.
Checked
Whether the ToolStripButton is pressed in or not. For example, the following pictures show that the New button has its Checked property set to True, and CheckState set to Checked when the ToolStrip is rendered with Professional and System rendering mode, respectively:
CheckOnClick
Whether the ToolStripButton should automatically appear pressed in and not pressed in when clicked.
CheckState
The state of the ToolStripButton: pressed, not pressed or an intermediate state.
How do I create toggle buttons in ToolStrip controls? A toggle button is a button that appears pressed when a user clicks on it and retains pressed appearance until the user clicks on it again. The following code snippet shows how to implement one. [VB]
33
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load NewToolStripButton.CheckOnClick = True AddHandler NewToolStripButton.CheckedChanged, AddressOf NewToolStripButton_CheckedChanged End Sub Private Sub NewToolStripButton_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles NewToolStripButton.CheckedChanged End Sub
[C#] private void Form1_Load(object sender, EventArgs e) { newToolStripButton.CheckOnClick = true; newToolStripButton.CheckedChanged += new EventHandler(newToolStripButton_CheckedChanged); } private void newToolStripButton_CheckedChanged(object sender, EventArgs e) { }
ToolStripLabel class ToolStripLabel provides label functionality in ToolStrip. This class inherits from ToolStripItem class and provides label functionality in ToolStrip. It represents a nonselectable ToolStripItem that renders text and images and can also display hyperlinks. Often overlooked, the ToolStripLabel is a very powerful item. It can be thought of as a ToolStripButton which doesn’t get focus by default and doesn’t render depressed and highlighted. Using the TextAlign and ImageAlign properties, you can use ToolStripLabel to create a label that can render text and images. It also has many properties that enable it to display one or more hyperlinks, and other properties that modify the appearance and behavior of hyperlinks. The following table lists some of the important properties. Property Names
Description
ActiveLinkColor
Gets or sets the color used to display an active link.
IsLink
Whether the ToolStripLabel is a hyperlink. When you set this to true, the entire text in the ToolStripLabel will be treated as a hyperlink. If you want to have mixed mode of linked and standard text, you can use a ToolStripControlHost.
LinkBehavior
Represents the behavior of a link. You can set it to one of the following values: SystemDefault, AlwaysUnderline, HoverUnderline, NeverUnderline.
LinkColor
The color used when displaying a normal link.
34
LinkVisited
Whether a link should be displayed as though it were visited.
VisitedLinkColor
The color used when displaying a link that that has been previously visited.
How do I get a mnemonic for a ToolStripComboBox, ToolStripTextBox or similar? ToolStripLabel supports mnemonic forwarding – simply precede your ToolStripControlHostItem with a ToolStripLabel with a mnemonic defined and you will get focus to the ToolStripControlHostItem when ALT+mnemonic is pressed. Do ToolStrips support a link control? Yes, ToolStripLabel has an IsLink property that will render it in a link style. LinkColor, LinkVisited and LinkBehavior are exposed.
ToolStripStatusLabel class This class inherits from ToolStripLabel class, and represents an individual panel in a StatusStrip control. A ToolStripStatusLabel can contain text or an icon that reflects the status of an application. Use the ToolStripItemCollection class to find, add, or remove ToolStripStatusLabel objects. Although ToolStripStatusLabel replaces and adds functionality to the StatusBarPanel control of previous versions, StatusBarPanel is retained for both backward compatibility and future use if you choose The following table describes the important properties: Property Names
Description
BorderSides
Indicates which sides of the ToolStripStatusLabel show borders.
BorderStyle
The border style of the ToolStripStatusLabel. Note: There is no builtin accomodation to render adjacent ToolStripStatusLabel’s borders as one.
Spring
A value indicating whether the ToolStripStatusLabel automatically fills the available space on the StatusStrip as the form is resized. See the paragraph below on this property for further details.
Using the Spring property Spring is supported only in StatusStrip and only with StatusStripLabels. It utilizes the underlying Table layout with a column style set to percentage to achieve the effect of the Spring panel filling the remaining space. Multiple ToolStripPanels set to Spring are sized equally, sharing the remaining space equally. For example,
35
class Form4 : Form { ToolStripStatusLabel middleLabel; public Form4() { // new StatusStrip StatusStrip ss = new StatusStrip(); // add left label ss.Items.Add("Left"); // handle middle label separately middleLabel = new ToolStripStatusLabel("Middle (Spring)"); middleLabel.Click += new EventHandler(middleLabel_Click); ss.Items.Add(middleLabel); // add right label ss.Items.Add("Right"); // Add the statusStrip to the controls collection this.Controls.Add(ss); } void middleLabel_Click(object sender, EventArgs e) { if (middleLabel.Spring) { middleLabel.Spring = false; middleLabel.Text = "Middle (Spring False)"; } else { middleLabel.Spring = true; middleLabel.Text = "Middle (Spring True)"; } } }
ToolStripSeparator class This class inherits from ToolStripItem class. It represents a line used to group related items of a ToolStrip or the dropdown items of a MenuStrip or ContextMenuStrip or other ToolStripDropDown control. The ToolStripSeparator is automatically spaced and oriented horizontally or vertically to accord with its container. What’s an easier way to enter a separator than creating a new one or picking from the dropdown? Simply enter a hyphen or dash (““) in either the designer template node or via the Add method on ToolStripItemCollection. This will automatically create a separator. Does ToolStrips automatically eliminate duplicate or trailing separators from layout? No, but the following code will do it for you:
36
void DropDown_Layout(object sender, LayoutEventArgs e) { StripSeparators(((ToolStrip)sender).Items); } public void StripSeparators(ToolStripItemCollection tsItems) { // ItemCollections should neither begin with, end with or contain adjacent separators. bool itemDisplayed = false; ToolStripItem lastSeparator = null; foreach (ToolStripItem tsItem in tsItems) { if (tsItem.Available) { if (tsItem is ToolStripSeparator) { // hide all separators tsItem.Visible = false; // only set in a separator that has a chance to be shown later // if no items have been displayed, no chance if (itemDisplayed) lastSeparator = tsItem; } else if (lastSeparator != null) { // show it when valid lastSeparator.Visible = true; } else { itemDisplayed = true; } } } }
ToolStripControlHost class This class inherits from ToolStripItem class and is the base class for ToolStripTextBox, ToolStripComboBox, ToolStripProgressBar. You can use this class to host your customized controls or any other Windows Forms control. It is designed to enable hosting of arbitrary Windows Forms controls in two ways: · Directly using the ToolStripControlHost and pass a control into its constructor; · Extending ToolStripControlHost itself; It is easier to wrap the control by extending ToolStripControlHost and implementing properties and methods that expose frequently used properties and methods of the control. You can also expose events for the control at the ToolStripControlHost level. toolStrip1.Items.Add(new ToolStripControlHost(new TrackBar()));
37
The follow table lists some of the important properties: Property Names
Description
CauseValidation
Whether the hosted control causes and raises validation events on other controls when the hosted control receives focus.
Control
Gets the Control that this ToolStripControlHost is hosting.
ControlAlign
The alignment of the control on the form.
How do I show a user control in a dropdown? private void button1_Click(object sender, EventArgs e) { ToolStripDropDown toolStripDropDown = new ToolStripDropDown(); // Create some user control UserControl1 uc = new UserControl1(); uc.Margin = Padding.Empty; toolStripDropDown.SuspendLayout(); // create the control host to host the user control //make sure it has no margin ToolStripControlHost host = new ToolStripControlHost(uc); host.Margin = Padding.Empty; // add the control host to the toolstripdropdown toolStripDropDown.Items.Add(host); // set the padding of the toolstripdropdown to be empty toolStripDropDown.Padding = Padding.Empty; // show no borders toolStripDropDown.Renderer = new BorderlessRenderer(); toolStripDropDown.ResumeLayout(); toolStripDropDown.Show(this.button1, 10, 10); } private class BorderlessRenderer : ToolStripProfessionalRenderer { protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { // do nothing } }
How do I wrap a Windows Forms control in ToolStripControlHost? Here are the 6 steps to host a Windows Forms control in a ToolStripControlHost by derivation. A MonthCalendar control is used as an example. 1. Derive a class that inherits from ToolStripControlHost. [C#] public class ToolStripMonthCalendar : ToolStripControlHost
38
[VB] Public Class ToolStripMonthCalendar Inherits ToolStripControlHost
2. Implement a default constructor that calls the base class constructor passing in the desired control. [C#] public ToolStripMonthCalendar() : base(new MonthCalendar()) { }
[VB] Public Sub New() MyBase.New(New MonthCalendar()) End Sub
3. Declare a property of the same type as the wrapped control and return Control as the correct type of control in the property's accessor. [C#] public MonthCalendar MonthCalendarControl { get { return Control as MonthCalendar; } }
[VB] Public ReadOnly Property MonthCalendarControl() As MonthCalendar Get Return CType(Control, MonthCalendar) End Get End Property
4. Expose other frequently used properties and methods of the wrapped control with properties and methods in the extended class. [C#] // Expose the MonthCalendar.FirstDayOfWeek as a property. public Day FirstDayOfWeek { get { return MonthCalendarControl.FirstDayOfWeek; } set { value = MonthCalendarControl.FirstDayOfWeek; } }
[VB] Public Property FirstDayOfWeek() As Day Get Return MonthCalendarControl.FirstDayOfWeek End Get Set(ByVal value As Day) value = MonthCalendarControl.FirstDayOfWeek End Set End Property
5. Optionally, override the OnSubscribeControlEvents, and OnUnsubscribeControlEvents methods and add the control events you want to expose. [C#] // Subscribe and unsubscribe the control events you wish to expose. protected override void OnSubscribeControlEvents(Control c)
39
{ // Call the base so the base events are connected. base.OnSubscribeControlEvents(c); // Cast the control to a MonthCalendar control. MonthCalendar monthCalendarControl = (MonthCalendar)c; // Add the event. monthCalendarControl.DateChanged += new DateRangeEventHandler(OnDateChanged); } protected override void OnUnsubscribeControlEvents(Control c) { // Call the base method so the basic events are unsubscribed. base.OnUnsubscribeControlEvents(c); // Cast the control to a MonthCalendar control. MonthCalendar monthCalendarControl = (MonthCalendar)c; // Remove the event. monthCalendarControl.DateChanged = new DateRangeEventHandler(OnDateChanged); }
[VB] Protected Overrides Sub OnSubscribeControlEvents(ByVal c As Control) ' Call the base so the base events are connected. MyBase.OnSubscribeControlEvents(c) ' Cast the control to a MonthCalendar control. Dim monthCalendarControl As MonthCalendar = _ CType(c, MonthCalendar) ' Add the event. AddHandler monthCalendarControl.DateChanged, _ AddressOf HandleDateChanged End Sub Protected Overrides Sub OnUnsubscribeControlEvents(ByVal c As Control) ' Call the base method so the basic events are unsubscribed. MyBase.OnUnsubscribeControlEvents(c) ' Cast the control to a MonthCalendar control. Dim monthCalendarControl As MonthCalendar = _ CType(c, MonthCalendar) ' Remove the event. RemoveHandler monthCalendarControl.DateChanged, _ AddressOf HandleDateChanged End Sub
6. Provide the necessary wrapping for the events you want to expose. [C#] // Declare the DateChanged event. public event DateRangeEventHandler DateChanged; // Raise the DateChanged event. private void OnDateChanged(object sender, DateRangeEventArgs e) {
40
if (DateChanged != null) { DateChanged(this, e); } }
[VB] ' Declare the DateChanged event. Public Event DateChanged As DateRangeEventHandler ' Raise the DateChanged event. Private Sub HandleDateChanged(ByVal sender As Object, _ ByVal e As DateRangeEventArgs) RaiseEvent DateChanged(Me, e) End Sub
ToolStripTextBox class This class inherits from ToolStripControlHost. It represents a text box in a ToolStrip that allows the user to enter text. This control has additional functionality that is not found in the standard Windows text box control, including multiline editing features such as AcceptsTab and AcceptsReturn. You can limit the amount of text entered into a ToolStripTextBox control by setting the MaxLength property to a specific number of characters. Use the CharacterCasing property to allow the user to type only uppercase, only lowercase, or a combination of uppercase and lowercase characters into the ToolStripTextBox control. To restrict text from being entered in a ToolStripTextBox control, you can create an event handler for the KeyDown event in order to validate each character entered in the control. You can also restrict all entry of data in a ToolStripTextBox control by setting the ReadOnly property to true. The following table lists some of the important properties. Property Names
Description
AcceptsReturn
Indicates whether pressing ENTER in a multiline TextBox control creates a new line of text in the control or activates the default button for the form.
AcceptsTab
Indicates whether pressing the TAB key in a multiline text box control types a TAB character in the control instead of moving the focus to the next control in the tab order.
AutoCompleteCustomSource A custom string collection to use when the AutoCompleteSource property is set to CustomSource enumeration. AutoCompleteSource
An option that controls how automatic completion works for the ToolStripTextBox.
CharacterCasing
Indicates whether the ToolStripTextBox control modifies the case of characters as they are typed.
41
HideSelection
Indicates whether the selected text in the text box control remains highlighted when the control loses focus.
Lines
The lines of text in a ToolStripTextBox control.
MaxLength
The maximum number of characters the user can type or paste into the text box control.
Modified
Indicates that the ToolStripTextBox control has been modified by the user since the control was created or its contents were last set.
ReadOnly
Indicates whether text in the ToolStripTextBox is readonly.
SelectedText
Indicates the currently selected text in the control.
SelectionLength
The number of characters selected in theToolStripTextBox.
SelectionStart
The starting point of text selected in theToolStripTextBox.
ShortCutsEnabled
Indicates whether the defined shortcuts are enabled.
TextBox
Gets the hosted TextBox control.
TextBoxTextAlign
Indicates how text is aligned in a TextBox control.
TextLength
Gets the length of text in the control.
ToolStripComboBox class This class inherits from ToolStripControlHost. It displays an editing field combined with a ListBox, allowing the user to select from the list or to enter new text. By default, a ToolStripComboBox displays an edit field with a hidden dropdown list. The DropDownStyle property determines the style of combo box to display. There is three dropdown styles: · Simple: the list always displays; · DropDownList: the text portion is not editable and you must select an arrow to view the dropdown list box; · DropDown (default): where the text portion is editable and the user must press the arrow key to view the list; To add objects to the list at run time, assign an array of object references with the AddRange method. The list then displays the default string value for each object. You can add individual objects with the Add method. In addition to display and selection functionality, the ToolStripComboBox also provides features that enable you to efficiently add items to the ToolStripComboBox and to find text within the items of the list: · The BeginUpdate and EndUpdate methods enable you to add a large number of items to the ToolStripComboBox without the control being repainted each time an item is added to the list.
42
· ·
The FindString and FindStringExact methods enable you to search for an item in the list that contains a specific search string. Use the SelectedIndex property to get or set the current item in the dropdown list, and use the SelectedItem property to get or set a reference to the current item in the drop down list.
The following table lists some of the important properties: Property Names
Description
AutoCompleteCustomSource The custom string collection to use when the AutoCompleteSource property is set to CustomSource enumeration. AutoCompleteMode
Indicates the text completion behavior of the ToolStripComboBox.
AutoCompleteSource
The source of complete strings used for automatic completion.
ComboBox
Gets a ComboBox in which the user can enter text, along with a list from which the user can select.
DropDownHeight
Controls the height (in pixels) of the dropdown portion box of a ToolStripComboBox.
DropDownStyle
Specifies the style of the ToolStripComboBox.
DropDownWidth
Controls the width(in pixels) of the of the dropdown portion of a ToolStripComboBox.
DroppedDown
Indicates whether the ToolStripComboBox currently displays its dropdown portion.
FlatStyle
Controls the appearance of the ToolStripComboBox: Flat, PopUp, Standard, or System.
IntegralHeight
Indicates whether the ToolStripComboBox should resize to avoid showing partial items.
MaxDropDownItems
The maximum number of items to be shown in the dropdown portion of the ToolStripComboBox.
MaxLength
The maximum number of characters allowed in the editable portion of a combo box.
SelectedIndex
The index specifying the currently selected item.
SelectedItem
Currently selected item in the ToolStripComboBox.
SelectedText
The text that is selected in the editable portion of a ToolStripComboBox.
SelectionLength
The number of characters selected in the editable portion of the ToolStripComboBox.
SelectionStart
The starting index of text selected in the ToolStripComboBox.
Sorted
Indicates whether the items in the ToolStripComboBox are sorted.
43
ToolStripProgressBar class This class inherits from ToolStripControlHost. It represents a Windows progress bar control contained in a StatusStrip. It visually indicates the progress of a lengthy operation (e.g, copying files or printing documents) by displaying a bar that fills in from left to right with the system highlight color as an operation progresses. It can only be oriented horizontally. The Maximum and Minimum properties define the range of values to represent the progress of a task. The Minimum property is typically set to a value of zero, and the Maximum property is typically set to a value indicating the completion of a task. For example, to display the progress properly when copying a group of files, the Maximum property could be set to the total number of files to be copied. The Value property represents the progress that the application has made toward completing the operation. Because the bar displayed in the control is a collection of blocks, the value displayed by the ToolStripProgressBar only approximates the Value property's current value. Based on the size of the ToolStripProgressBar, the Value property determines when to display the next block. There are a number of ways to modify the value displayed by the ToolStripProgressBar other than changing the Value property directly. You can use the Step property to specify a specific value to increment the Value property by, and then call the PerformStep method to increment the value. To vary the increment value, you can use the Increment method and specify a value by which to increment the Value property. ToolStripProgressBar replaces the older ProgressBar control, which is nevertheless retained for backward compatibility. The following table lists some of the important members. Property Names
Description
Maximum
Controls the upper bound of the range that is defined for this ToolStripProgressBar.
Minimum
Controls the lower bound of the range that is defined for this ToolStripProgressBar.
Step
The amount by which to increment the current value of the ToolStripProgressBar when the PerformStep method is called.
Style
The style of the ToolStripProgressBar.
Value
The current value of the ToolStripProgressBar.
Method Names
Description
Increment
Advances the current position of the progress bar by the specified amount.
PerformStep
Advances the current position of the progress bar by the amount of the Step property.
44
ToolStripDropDownItem class This class inherits from ToolStripItem. It is the abstract base class for ToolStripDropDownButton, ToolStripMenuItem, and ToolStripSplitButton controls. It provides basic functionality for controls that display a ToolStripDropDown when these controls are clicked. The following table lists some of the important properties. Property Names
Description
DropDown
The ToolStripDropDown that will be displayed when this ToolStripDropDownItem is clicked.
DropDownDirection
Indicates the direction in which the ToolStripDropDownItem emerges from its parent container. These four values should be used with the Show() method. They are positioned absolutely and may overlap existing dropdowns. · AboveLeft · AboveRight · BelowLeft · BelowRight These three values are for use with Menus and will be automatically positioned to not layer over previous menus: · Default: used with either, default, respects RightToLeft · Left: used with ToolStripDropDownMenu or ContextMenuStrip. It forces left rather than respecting RightToLeft. · Right: used with ToolStripDropDownMenu or ContextMenuStrip. It forces right rather than respecting RightToLeft.
DropDownItems
The collection of items in the ToolStripDropDown that is associated with this ToolStripDropDownItem.
HasDropDownItems
Indicates whether the ToolStripDropDownItem has ToolStripDropDown controls associated with it.
IsOnDropDown
Indicates whether the container of the current Control is a ToolStripDropDown.
IsOnOverflow
Indicates whether the Placement property is set to Overflow.
Pressed
Indicates whether the ToolStripDropDownItem is in the pressed state.
DropDownItemClicked, DropDownItem You can populate a dropdown via two different methods: 1. Populating the DropDownItems collection; 2. Assigning a created ContextMenuStrip to the ToolStripDropDownItem’s DropDown property;
45
Another notable feature of ToolStripDropDownItem is the DropDownItemClicked event. This allows you a convenient way to not have to sync each item in a ToolStripDropDown’s click event. And you don’t have to search into the collection either, we just hand you back the item that was clicked on. The following sample shows these concepts. // populate the DropDownItems Collection ToolStripMenuItem veggiesMenuItem = new ToolStripMenuItem("Veggies"); veggiesMenuItem.DropDownItems.Add("Asparagus"); veggiesMenuItem.DropDownItems.Add("Bok Choy"); veggiesMenuItem.DropDownItems.Add("Cauliflower"); // Hook up the handler veggiesMenuItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(myDropDownItemClicked); // assign a dropdown ContextMenuStrip cms = new ContextMenuStrip(); cms.Items.Add("Apples"); cms.Items.Add("Bananas"); cms.Items.Add("Cherries"); ToolStripMenuItem fruitMenuItem = new ToolStripMenuItem("Fruit"); fruitMenuItem.DropDown = cms; // Hook up the handler fruitMenuItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(myDropDownItemClicked); // menustrip MenuStrip ms = new MenuStrip(); ms.Items.Add(fruitMenuItem); ms.Items.Add(veggiesMenuItem); this.Controls.Add(ms);
ToolStripMenuItem class This class inherits from ToolStripDropDownItem. It represents a selectable option displayed on a MenuStrip or ContextMenuStrip. In order for a ToolStripMenuItem to be displayed, you must add it to a MenuStrip or ContextMenuStrip. The ToolStripMenuItem class provides properties that enable you to configure the appearance and functionality of a menu item. · Use the Checked property to display a check mark next to a menu item. This feature is to identify a menu item that is selected in a list of mutually exclusive menu items. For example, if you have a set of menu items for setting the color of text in a TextBox control, use the Checked property to identify which color is currently selected. · Use the ShortcutKeys property to define a keyboard combination that can be pressed to select the menu item. Although ToolStripMenuItem replaces and adds functionality to the MenuItem control of previous versions, MenuItem is retained for both backward compatibility and future use if you choose. For example, the following figure shows that the Colors menu contains five ToolStripMenuItem, where the first one has its Checked property set to True, ShortCutKeys property set to Ctrl+R, ShortCutKeyDisplayString set to Ctrl+R, and ShowShortCurKeys set to True:
46
The following table lists some of the important properties: Property Names
Description
Checked
Indicates whether the ToolStripMenuItem is checked.
CheckOnClick
Indicates whether the ToolStripMenuItem should automatically appear checked and unchecked when clicked.
CheckState
Indicates whether a ToolStripMenuItem is in the checked, unchecked, or indeterminate state.
IsMdiWindowListEntry
Indicates whether the ToolStripMenuItem appears on a multiple document interface (MDI) window list. It is a ReadOnly property.
ShortcutKeyDisplayString
Controls the shortcut key text.
ShortcutKeys
Controls the shortcut keys associated with the ToolStripMenuItem.
ShowShortcutKeys
Indicates whether the shortcut keys that are associated with the ToolStripMenuItem are displayed next to the ToolStripMenuItem.
How do I clone a ToolStripMenuItem? By default, ToolStripMenuItem does not contain an implementation for cloning. Here's the code for ToolStripMenuItem.Clone. An alternate solution is to implement IBindableComponent and data bind your menu item to a command which drives the Text/Image/Enabled/Available properties. public class ClonableToolStripMenuItem : ToolStripMenuItem { public ClonableToolStripMenuItem() { } internal ToolStripMenuItem Clone() { // dirt simple clone just properties, no subitems ClonableToolStripMenuItem menuItem = new ClonableToolStripMenuItem(); menuItem.Events.AddHandlers(this.Events); menuItem.AccessibleName = this.AccessibleName; menuItem.AccessibleRole = this.AccessibleRole; menuItem.Alignment = this.Alignment; menuItem.AllowDrop = this.AllowDrop; menuItem.Anchor = this.Anchor; menuItem.AutoSize = this.AutoSize; menuItem.AutoToolTip = this.AutoToolTip;
47
menuItem.BackColor = this.BackColor; menuItem.BackgroundImage = this.BackgroundImage; menuItem.BackgroundImageLayout = this.BackgroundImageLayout; menuItem.Checked = this.Checked; menuItem.CheckOnClick = this.CheckOnClick; menuItem.CheckState = this.CheckState; menuItem.DisplayStyle = this.DisplayStyle; menuItem.Dock = this.Dock; menuItem.DoubleClickEnabled = this.DoubleClickEnabled; menuItem.Enabled = this.Enabled; menuItem.Font = this.Font; menuItem.ForeColor = this.ForeColor; menuItem.Image = this.Image; menuItem.ImageAlign = this.ImageAlign; menuItem.ImageScaling = this.ImageScaling; menuItem.ImageTransparentColor = this.ImageTransparentColor; menuItem.Margin = this.Margin; menuItem.MergeAction = this.MergeAction; menuItem.MergeIndex = this.MergeIndex; menuItem.Name = this.Name; menuItem.Overflow = this.Overflow; menuItem.Padding = this.Padding; menuItem.RightToLeft = this.RightToLeft; menuItem.ShortcutKeys = this.ShortcutKeys; menuItem.ShowShortcutKeys = this.ShowShortcutKeys; menuItem.Tag = this.Tag; menuItem.Text = this.Text; menuItem.TextAlign = this.TextAlign; menuItem.TextDirection = this.TextDirection; menuItem.TextImageRelation = this.TextImageRelation; menuItem.ToolTipText = this.ToolTipText; menuItem.Available = this.Available; if (!AutoSize) { menuItem.Size = this.Size; } return menuItem; } }
ToolStripSplitButton class This class inherits from ToolStripDropDownItem. It represents a combination of a standard button on the left and a dropdown button on the right, or the other way around if the value of RightToLeft is set to Yes.
48
The following table lists some of the important properties. Property Names
Description
AutoToolTip
Indicates whether default or custom ToolTip text is displayed on the ToolStripSplitButton. By default, the value is set to True, and a ToolStripSplitButton uses its Text property for the ToolTip text. To display custom text via the ToolTipText property, you need to set the AutoToolTip property to False. AutoToolTip is set to true by default for these classes only • ToolStripButton • ToolStripDropDownButton • ToolStripSplitButton
ButtonBounds
Gets the size and location of the standard button portion of a ToolStripSplitButton.
ButtonPressed
Indicates whether the standard button portion of the ToolStripSplitButton is in the pressed state.
ButtonSelected
Indicates whether the standard button portion of a ToolStripSplitButton is selected.
DefaultItem
Controls the portion of the ToolStripSplitButton that is activated when the control is first selected. See the “DefaultItem” paragraph for details.
DoubleClickEnabled
Indicates whether the control can be activated by doubleclicking the mouse.
DropDownButtonBounds
Gets the size and location (in screen coordinates) of the drop
49
down button portion of a ToolStripSplitButton. DropDownButtonPressed
Indicates whether the dropdown portion of the ToolStripSplitButton is in the pressed state.
DropDownButtonSelected
Indicates whether the dropdown button portion of a ToolStripSplitButton is selected.
DropDownButtonWidth
Controls the width (in pixels) of the dropdown button portion of a ToolStripSplitButton.
RightToLeft
Indicates whether items are to be placed from right to left and text is to be written from right to left. RightToLeft set to False:
RightToLeft set to True:
SplitterBounds
Gets the boundaries of the separator between the standard and dropdown button portions of a ToolStripSplitButton.
DefaultItem ToolStripSplitButton.DefaultItem is an easy mechanism to synchronize the click event from the ToolStripSplitButton’s item chosen from the dropdown with the one rendered in the button area. The following sample assumes you have a click handler associated with each item in the dropdown and have set a default item as part of initialization. ToolStripSplitButton veggieButton = new ToolStripSplitButton("Veggies"); veggieButton.DropDownItems.Add("Asparagus"); veggieButton.DropDownItems.Add("Bok Choy"); veggieButton.DropDownItems.Add("Cauliflower"); veggieButton.DisplayStyle = ToolStripItemDisplayStyle.Text; veggieButton.DropDownItemClicked += new ToolStripItemClickedEventHandler(veggieButton_DropDownItemClicked); veggieButton.DefaultItemChanged += new EventHandler(veggieButton_DefaultItemChanged); // menustrip
50
ToolStrip ts = new ToolStrip(); ts.Items.Add(veggieButton); this.Controls.Add(ts); } void veggieButton_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) { ((ToolStripSplitButton)sender).DefaultItem = e.ClickedItem; ((ToolStripSplitButton)sender).Text = e.ClickedItem.Text; }
ToolStripDropDownButton class This class inherits from ToolStripDropDownItem. It represents a control that when clicked displays an associated ToolStripDropDown from which the user can select a single item.
The following table lists some of the important properties.
Property Names
Description
AutoToolTip
Indicates whether default or custom ToolTip text is displayed on the ToolStripDropDownButton. By default, the value is set to True, and a ToolStripDropDownButton uses its Text property for the ToolTip text. To display custom text via the ToolTipText property, you need to set the AutoToolTip property to False.
51
AutoToolTip is set to true by default for these classes only • ToolStripButton • ToolStripDropDownButton • ToolStripSplitButton ShowDropDownArrow
Indicates whether an arrow is displayed on the ToolStripDropDownButton, which indicates that further options are available in a dropdown list.
ToolStripOverflowButton class This class inherits from ToolStripDropDownButton. It hosts a ToolStripDropDown that displays items that overflow the ToolStrip.
ToolStripManager class This class inherits from System.Object. It is a static class that handles application wide ToolStrip related tasks such as merging, settings and renderer exposure. The following table lists some of the important members: Property Names
Description
Renderer
Controls the default painting styles for the form.
RenderMode
Control the default theme for the form.
VisualStylesEnabled
Indicates whether a ToolStrip is rendered using XP visual style.
Method Names
Description
FindToolStrip
Finds the specified ToolStrip or a type derived from ToolStrip.
IsShortcutDefined
Indicates whether the specified shortcut key is used by any of the ToolStrip controls of a form.
IsValidShortcut
Indicates whether a defined shortcut key is valid.
52
LoadSettings
Loads settings (ToolStrip and ToolStripItem locations) for a Form.
Merge
Combines ToolStrip controls.
RevertMerge
Undoes a merging of two ToolStrip objects.
SaveSettings
Saves settings (ToolStrip and ToolStripItem locations) for the specified Form.
Event Names
Description
RendererChanged
Occurs when the value of the Renderer property changes.
Note: The Renderer and RenderMode properties will be further discussed in the Rendering section of the training later. How do I use the ToolStripManager to persist and restore the entire ToolStrip tree? The ToolStripManager provides the LoadSettings and SaveSettings methods. They will be further discussed in the Settings section of this training. How do I apply a custom ToolStrip Renderer to an Application using ToolStripManager? You can customize the appearance of your ToolStrip controls individually or for all the ToolStrip controls in your application. To customize the appearance for all the ToolStrip controls at the application level, you need to set the ToolStripManager’s Renderer property to an instance of a custom renderer class. Step 1: Create a custom Renderer class: [VB] ' This sample type demonstrates a custom renderer. It overrides the ' OnRenderMenuItemBackground and OnRenderButtonBackground methods ' to customize the backgrounds of MenuStrip items and ToolStripbuttons. Class CustomProfessionalRenderer Inherits ToolStripProfessionalRenderer Protected Overrides Sub OnRenderMenuItemBackground(ByVal e As ToolStripItemRenderEventArgs) ' Add your implementation here End Sub Protected Overrides Sub OnRenderButtonBackground(ByVal e As ToolStripItemRenderEventArgs) ' Add your implementation here End Sub End Class
[C#] // This sample type demonstrates a custom renderer. It overrides the // OnRenderMenuItemBackground and OnRenderButtonBackground methods // to customize the backgrounds of MenuStrip items and ToolStripbuttons. class CustomProfessionalRenderer : ToolStripProfessionalRenderer { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { // Add your implementation here }
53
protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) { // Add your implementation here } }
Step 2: Apply the custom renderer to all ToolStrip components in the entire application. ' Assign the custom renderer at the application level. This will ' affect all ToolStrip components at the application level. menuStrip1.RenderMode = ToolStripRenderMode.ManagerRenderMode toolStrip1.RenderMode = ToolStripRenderMode.ManagerRenderMode ToolStripManager.Renderer = New CustomProfessionalRenderer()
Note: if you do not want to apply the custom renderer to all ToolStrip components at the application level, then you do not need to do this through the ToolStripManager. Instead, you can apply the custom render to individual ToolStrip objects. For example: ' Assign the custom renderer to the MenuStrip control only. menuStrip1.Renderer = New CustomProfessionalRenderer()
Or ' Assign the custom renderer to the ToolStrip control only. toolStrip1.Renderer = New CustomProfessionalRenderer()
Layout By default, the ToolStrip control utilizes a StackWithOverflow layout that supports overflow and item alignment. Stack refers to how the aside each other at both ends of items are laid out within the ToolStrip where each item is stacked the ToolStrip. The ToolStrip class can use one of the following ToolStripLayoutStyle values to specify the possible alignments with which the items of a ToolStrip can be displayed. · Stack layouts o StackWithOverflow o HorizontalStackWithOverflow o VertocalStackWithOverflow · Non stack layouts o Flow o Table The sizing grip will not be displayed unless you also set the LayoutStyle property to one of the overflow values. If the LayoutStyle property is set to Flow or Table, the sizing grip will not be displayed, and you lose the overflow feature as well. Stack layouts 1. StackWithOverflow: Default for ToolStrip. This layout style automatically alters its layout based on the orientation property of the ToolStrip to handle drag to dock scenarios. 2. VerticalStackWithOverflow: Just like StackWithOverflow except always renders as vertical.
54
3. HorizontalStackWithOverflow: Just like StackWithOverflow except always renders horizontal. Features notes with Stack Layouts 1. ToolStripItem.Alignment controls which side of the ToolStrip the item is aligned to. 2. ToolStripItem.Overflow controls whether an item can overflow to the ToolStripOverflow dropdown Always, AsNeeded, or Never. 3. When items do not fit within the ToolStrip, an Overflow button is rendered. Additional items appear in the ToolStripOverflow dropdown. 4. On the LayoutCompleted event, the ToolStripItem.Placement property can be inspected to see if an item was placed on the Main toolstrip, the Overflow toolstrip, or if it is not currently showing (usually because the item did not fit on Main and it was set to Overflow.Never). 5. A ToolStrip can be “movable” if it is placed in a ToolStripPanel and its GripStyle is set to Visible. NonStack layouts 1. Flow: Default for ContextMenuStrip, ToolStripDropDownMenu, and ToolStripOverflow, and is very similar to the FlowLayoutPanel. For example, the following code snippet creates the ToolStrip below: toolStrip1.LayoutStyle = ToolStripLayoutStyle.Flow; FlowLayoutSettings settings = toolStrip1.LayoutSettings as FlowLayoutSettings; settings.FlowDirection = FlowDirection.RightToLeft;
Features notes with FlowLayouts · All of the properties/methods of the FlowLayoutPanel FlowBreak, WrapContents, FlowDirection, etc are exposed off the ToolStrip. LayoutSettings object (LayoutSettings must be casted into a FlowLayoutSettings class). · The ToolStripItem.Dock and ToolStripItem.Anchor properties can be used in code to align the items within the row. · The ToolStripItem.Alignment property is ignored. · On the LayoutCompleted event, the ToolStripItem.Placement property can be inspected to see if an item was placed on the Main toolstrip or didn’t fit (None). · The ToolStrip grip is not rendered, thus a ToolStrip with LayoutStyle = Flow in a ToolStripPanel cannot be moved. · The ToolStrip overflow button is not rendered, ToolStripItem.Overflow is ignored. 2. Table: Default for StatusStrip, and is very similar to TableLayoutPanel. For example, the following code snippet creates the ToolStrip below: toolStrip1.LayoutStyle = ToolStripLayoutStyle.Table; TableLayoutSettings settings = toolStrip1.LayoutSettings as TableLayoutSettings; settings.ColumnCount = 3; settings.RowCount = 5;
55
Features notes with TableLayout · All of the properties/methods of the TableLayoutPanel – RowCount, ColumnCount, RowSpan, ColumnSpan, RowStyles, ColumnStyles are exposed off the ToolStrip. LayoutSettings object (LayoutSettings must be casted into a TableLayoutSettings class). · The ToolStripItem.Dock and ToolStripItem.Anchor properties can be used in code to align the items within the cell. · The ToolStripItem.Alignment property is ignored. · On the LayoutCompleted event, the ToolStripItem.Placement property can be inspected to see if an item was placed on the Main toolstrip or didn’t fit (None). · The ToolStrip grip is not rendered, thus a ToolStrip with LayoutStyle = Table in a ToolStripPanel cannot be moved. · The ToolStrip overflow button is not rendered, ToolStripItem.Overflow is ignored. Note: For StatusStrip, all “Spring” columns are set to 100%, all other columns are set to AutoSize in an overridable method called OnSpringTableLayoutCore. The following table describes the layout styles supported by each ToolStrip class including the default value. ToolStrip classes
Supported Layout
Default Layout
ToolStrip
Flow, HorizontalStackWithOverflow, StackWithOverflow, Table, VerticalStackWithOverflow
HorizontalStackWithOverflow
MenuStrip
Flow, HorizontalStackWithOverflow, StackWithOverflow, Table, VerticalStackWithOverflow
HorizontalStackWithOverflow
StatusStrip
Flow, HorizontalStackWithOverflow, StackWithOverflow, Table, VerticalStackWithOverflow
Table
ContextMenuStrip
Flow, HorizontalStackWithOverflow,
Flow
56
StackWithOverflow, Table, VerticalStackWithOverflow
The ToolStrip class also provides three events related to layout: Event names
Description
Layout
Occurs when the ToolStrip is about to layout its contents.
LayoutStyleChanged
Fires when the value of the LayoutStyle property changes. You can handle this event to adjust the display of the ToolStrip controls accordingly. For example, you can use the following code snippet to change the text direction on a MenuStrip depending on its Orientation in its LayoutStyleChanged event handler: if (menuStrip1.Orientation == Orientation.Vertical) { menuStrip1.TextDirection = ToolStripTextDirection.Vertical270; } else { menuStrip1.TextDirection = ToolStripTextDirection.Horizontal; }
LayoutCompleted
Occurs after layout and placement of items on the ToolStrip completes.
Dock ToolStrips have three main usage patterns: 1. Joined in ToolStripPanel; 2. Docked within a parent container; 3. Absolutely positioned; ToolStrips follow the same rules as other Windows Forms controls with regards to docking, except when they are joined into a ToolStripPanel. See ToolStripPanelError! Reference source not found. for additional information. Overflow
57
To be precise, overflow is a feature of the ToolStrip’s default LayoutStyle (StackWithOverflow), not of the ToolStrip control itself. You determine what overflow action is preferred via the Overflow property (Always, Never, AsNeeded). To determine dynamically where each item was laid out, sync the LayoutCompleted event check item Placement (Main, Overflow, None). Property changes here will cause another layout; be wary of recursive code here. An item will not be partially laid out if it would result in a truncation – it will not be laid out and Placement will be none.
How do I change layout characteristics not directly exposed in ToolStrip? You can access the LayoutSettings object offered at the ToolStrip level and cast to the appropriate type and access the properties there. The following is an example of changing the flow direction of a ToolStrip. toolStrip1.LayoutStyle = ToolStripLayoutStyle.Flow; ((FlowLayoutSettings)toolStrip1.LayoutSettings).FlowDirection = FlowDirection.BottomUp;
How can I do dynamic text rotation as my ToolStrip changes orientation? You can sync the LayoutStyleChanged event on the ToolStrip. This sample rotates the text to Vertical90 on vertical layouts. For best results, start with a ToolStrip with standard items and make sure all ToolStripButton display styles are set to ImageAndText. private void toolStrip1_LayoutStyleChanged(object sender, EventArgs e) { if (toolStrip1.LayoutStyle == ToolStripLayoutStyle.VerticalStackWithOverflow) { toolStrip1.TextDirection = ToolStripTextDirection.Vertical90; foreach (ToolStripItem tsi in toolStrip1.Items) { if (tsi is ToolStripButton) { tsi.TextImageRelation = TextImageRelation.ImageAboveText; } } } else { toolStrip1.TextDirection = ToolStripTextDirection.Horizontal; foreach (ToolStripItem tsi in toolStrip1.Items) { if (tsi is ToolStripButton) { tsi.TextImageRelation = TextImageRelation.ImageBeforeText; } } } }
How do I implement a dynamic overflow?
58
The following sample demonstrates basic overflow. Run the form and resize to the see the output after layout. ToolStrip t = new ToolStrip(); t.LayoutCompleted += new EventHandler(t_LayoutCompleted); ToolStripButton tsb1 = new ToolStripButton("1 Left Never "); tsb1.Overflow = ToolStripItemOverflow.Never; ToolStripButton tsb2 = new ToolStripButton("2 Right AsNeeded"); tsb2.Alignment = ToolStripItemAlignment.Right; ToolStripButton tsb3 = new ToolStripButton("3 Left AsNeeded"); ToolStripButton tsb4 = new ToolStripButton("4 Right AsNeeded"); tsb4.Alignment = ToolStripItemAlignment.Right; ToolStripButton tsb5 = new ToolStripButton("5 Left Always "); tsb5.Overflow = ToolStripItemOverflow.Always; t.Items.AddRange(new ToolStripItem[] {tsb1, tsb2, tsb3, tsb4, tsb5}); this.Controls.Add(t);
void t_LayoutCompleted(object sender, EventArgs e) { foreach (ToolStripItem item in ((ToolStrip)(sender)).Items) { System.Diagnostics.Debug.WriteLine(item.ToString() + " Placement: " + item.Placement.ToString()); }
} How do I implement a custom DropDown where overflow items are handled manually? The default overflow dropdown is available programmatically. But to customize the layout of the overflow, you can also simply assign your custom ToolStripDropDownMenu to the dropdown property. Below is an example of a custom dropdown – and handling overflow items manually. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsApplication65 { public partial class Form1 : Form { ContextMenuStrip cms = new ContextMenuStrip(); ToolStrip toolstrip = new ToolStrip(); ToolStripButton placeholder = new ToolStripButton(); ToolStripItem[] originalItemCollection; public Form1()
59
{ InitializeComponent(); toolstrip.Layout += new LayoutEventHandler(toolstrip_Layout); toolstrip.LayoutCompleted += new EventHandler(toolstrip_LayoutCompleted); // the is a way to fake the overflow has stuff in it, therefore the button will // get rendered. // placeholder.Overflow = ToolStripItemOverflow.Always; toolstrip.Items.Add(placeholder); toolstrip.SuspendLayout(); // add some items. toolstrip.Items.Add("1"); toolstrip.Items.Add("2"); toolstrip.Items.Add("3"); toolstrip.Items.Add("4"); toolstrip.Items.Add("5"); toolstrip.Items.Add("6"); toolstrip.Items.Add("7"); toolstrip.Items.Add("8"); // we need to snap the items collection before performing a layout // as the LayoutCompleted will remove items from the items collection. originalItemCollection = new ToolStripItem[toolstrip.Items.Count]; toolstrip.Items.CopyTo(originalItemCollection, 0); toolstrip.ResumeLayout();
this.Controls.Add(toolstrip); toolstrip.OverflowButton.DropDown = cms; } void toolstrip_Layout(object sender, LayoutEventArgs e) { // push all items back into main toolstrip collection if (originalItemCollection != null) { toolstrip.Items.AddRange(originalItemCollection); } } void toolstrip_LayoutCompleted(object sender, EventArgs e) { ToolStripItemCollection items = toolstrip.Items; toolstrip.SuspendLayout(); cms.SuspendLayout(); // turn overflow button off placeholder.Available = false; for (int i = items.Count 1; i > 1; i) { ToolStripItem item = items[i]; System.Diagnostics.Debug.WriteLine(item.ToString() + " Placement: " + item.Placement.ToString()); if (item.Placement == ToolStripItemPlacement.Overflow) { if (item != placeholder) { cms.Items.Insert(0, item);
60
// turn overflow button on placeholder.Available = true; } } } cms.ResumeLayout(false); toolstrip.ResumeLayout(true); } } }
ToolStripContainer class This class provides panels on each side of the form and a central panel that can hold one or more controls. It consists of an expandable and collapsible ToolStripPanel on each side of the control, and a central ToolStripContentPanel. Use a ToolStripPanel to hold one or more ToolStrip, MenuStrip, or StatusStrip controls. Use the central ToolStripContentPanel to hold other controls. When you drag a nonToolStrip Windows Forms control and drop on the ToolStripContainer, it will be automatically placed on the ToolStripContentPanel. Sides – ToolStripPanels The ToolStripPanels on the sides are not removable from the container, but can be hidden via their respective visible property(Top > TopToolStripPanelVisble, etc). Visible false means they would not participate in the drag to dock scnearions. // to hide left and right panels toolStripContainer1.LeftToolStripPanelVisible = false; toolStripContainer1.RightToolStripPanelVisible = false;
Center – ContentPanel The Content panel provides a way to get Renderer support into the body of your form to create a consistent look. It cannot be hidden. It does supports transparency and backcolor, but it may be prudent in many scenarios that require this to dock ToolStripPanels to the side instead. Design Time ToolStripContainer offers several design time features not found on other controls. Below is a description of a few of these. Expandable handles On each ToolStripPanel we offer a handle to temporarily expand the ToolStripPanel to ease rearrangement of ToolStrips and enlarge the drop area. These are not rendered at runtime. Reparent Controls A designer verb, also shown on the Designer Action panel, is Reparent controls. This takes all controls on the form and reparents them to the ToolStripContainer. All ToolStrips are mapped
61
into the ToolStripPanels and all other controls parented to the form are reparented to the ContentPanel. Below is a mini walkthrough on how to add a ToolStripContainer to a form and ToolStrips to the top panel. Step 1. Drag ToolStripContainer from the ToolBox and drop it on the form. Notice the autopopped smart tag for you to control the visibility of the top, bottom, left and right panels, and the Dock property of the ToolStripContainer.
Step 2. Dock Fill ToolStripContainer by selecting “Dock Fill in Form” since the default Dock value is none. The top panel is expanded automatically by default. Note glyph arrow direction reverses.
62
Step 3. Add ToolStrip to the top panel. Note glyph arrow direction reverses back.
Step 4. Expand the top panel. Note glyph arrow direction reverses again.
63
Step 5. Add another ToolStripto the top panel, and notice that glyph arrow direction reverses back.
The following table lists some of the important properties of the ToolStripContainer class. Property names
Description
BottomToolStripPanel
Gets the bottom panel of the ToolStripContainer.
BottomToolStripPanelVisible
Indicates whether the bottom panel of the ToolStripContainer is visible.
ContentPanel
Gets the center panel of the ToolStripContainer.
LeftToolStripPanel
Gets the left panel of the ToolStripContainer.
LeftToolStripPanelVisible
Indicates whether the left panel of the ToolStripContainer is visible.
RightToolStripPanel
Gets the right panel of the ToolStripContainer.
RightToolStripPanelVisible
Indicates whether the right panel of the ToolStripContainer is visible.
TopToolStripPanel
Gets the top panel of the ToolStripContainer.
TopToolStripPanelVisible
Indicates whether the top panel of the ToolStripContainer is visible.
There are several classes related to the ToolStripContainer class. The following section describes each of them.
64
ToolStripPanel class This class represents the four side panels of a ToolStripContainer. It provides space for other controls to share horizontal or vertical spaces. Property names
Description
Renderer
A ToolStripRenderer used to customize the appearance of a ToolStripPanel.
RenderMode
The painting styles to be applied to the ToolStripPanel.
RowMargin
Controls the spacing (in pixels) between the ToolStripPanelRows and the ToolStripPanel.
Rows
Gets the ToolStripPanelRows in this ToolStripPanel.
Feature highlights of the four ToolStrip panels · The TopToolStripPanel, BottomToolStripPanel, LeftToolStripPanel and RightToolStripPanel are exposed as top level properties of the ToolStripContainer; · Default RenderMode is ManagerRenderMode; · TopPanelVisible, BottomPanelVisible, LeftPanelVisible and RightPanelVisible properties to control the visibility of the top, button left, right ToolStrip panels respectively. · Zorder cannot be configured by user.
ToolStripPanelRow class This class represents a row of a ToolStripPanel that can contain controls. Property names
Description
Control
Gets the controls in the ToolStripPanelRow.
DisplayRectangle
The display area of the control.
LayoutEngine
Gets an instance of the control's layout engine.
Orientation
The layout direction of the ToolStripPanelRow relative to its containing ToolStripPanel.
ToolStripPanel
Gets the ToolStripPanel that contains the ToolStripPanelRow.
ToolStripContentPanel class This class represents the center panel of a ToolStripContainer control. Property names
Description
Renderer
A ToolStripRenderer used to customize the appearance of a ToolStripContentPanel.
65
RenderMode
The painting styles to be applied to the ToolStripContentPanel.
Feature highlights of the Content Panel · Not removable. · Zorder cannot be configured by user. · No context menu additions. · Default RenderMode is set to System. This means that ContentPanel.BackColor is used to render the backcolor. How do I programmatically move ToolStrips within or across ToolStripPanels? Within a ToolStrip: Simply set the ToolStrip Location property. Across ToolStrips: Either add the ToolStrip to the ToolStripPanel’s Controls collection or use Join(ToolStrip). NOTE: Join() simulates the drop operation of a ToolStrip and is order dependent.
Settings The ToolStripManager class provides the LoadSettings and SaveSettings methods to allow the user to save or restore the entire ToolStrip tree. This allows you to enable drag to dock scenarios in the ToolStripPanel and AllowItemReorder without having to manage restoring or saving that state. The following code snippet demonstrates using the LoadSettings and SaveSettings methods to persist and reset settings. [C#] private void Form1_Load(object sender, EventArgs e) { //Save the current setting of the form using the "Reset" settings //key when you first load the form ToolStripManager.SaveSettings(this, "Reset"); //Load the form's settings ToolStripManager.LoadSettings(this); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { //Save the form's new settings when you close the form. ToolStripManager.SaveSettings(this); }
private void buttonResetSettings_Click(object sender, EventArgs e) { //Load the form's original setting that was //saved using the "Reset" settings key
66
ToolStripManager.LoadSettings(this, "Reset"); }
[VB] Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Save the current setting of the form using the "Reset" 'settings key when you first load the form ToolStripManager.SaveSettings(Me, "Reset") 'Load the form's settings ToolStripManager.LoadSettings(Me) End Sub Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing 'Save the form's new settings when you close the form. ToolStripManager.SaveSettings(Me) End Sub Private Sub buttonResetSettings_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonResetSettings.Click 'Load the form's original setting that was 'saved using the "Reset" settings key ToolStripManager.LoadSettings(Me, "Reset") End Sub
Running the above code snippet, you will get the following results: 1. Form is loaded with its original settings:
2. Drag the ToolStrip to dock to the left side of the form. Close the form and open it again, the new settings are persisted:
67
3. Click on the Reset Settings button to revert the settings so the original setting is used:
Using MenuStrip in MDI applications The MDI related features around MenuStrip are described below. Using a MenuStrip in MDI requires Form.MainMenuStrip to be set in order to identify the controlling MenuStrip. It will be used for child window control menu merging when children are maximized. Automatic merging between child and parent forms is triggered by child activation. ToolStripContainer is not designed to be used on a MDI parent form. When you add a ToolStripContainer to the MDI parent form, it will cover the entire MDI client area and the MDI child form will not be displayed. You can add ToolStrip, MenuStrip and StatusStrip to MDI parent window, but they will not be movable. That means you cannot drag them to dock to a different side of the client area of the MDI parent form. In order to implement movable menus on a MDI parent window, you will need to add individual ToolStripPanel and implement the move yourself.
68
How do I use ToolStripPanel in MDI applications? [VB] ' This code example demonstrates how to use ToolStripPanel ' controls with a multiple document interface (MDI). Public Class Form1 Inherits Form Public Sub New() ' Make the Form an MDI parent. Me.IsMdiContainer = True ' Create ToolStripPanel controls. Dim tspTop As New ToolStripPanel() Dim tspBottom As New ToolStripPanel() Dim tspLeft As New ToolStripPanel() Dim tspRight As New ToolStripPanel() ' Dock the ToolStripPanel controls to the edges of the form. tspTop.Dock = DockStyle.Top tspBottom.Dock = DockStyle.Bottom tspLeft.Dock = DockStyle.Left tspRight.Dock = DockStyle.Right ' Create ToolStrip controls to move among the ' ToolStripPanel controls. ' Create the "Top" ToolStrip control and add ' to the corresponding ToolStripPanel. Dim tsTop As New ToolStrip() tsTop.Items.Add("Top") tspTop.Join(tsTop) ' Create the "Bottom" ToolStrip control and add ' to the corresponding ToolStripPanel. Dim tsBottom As New ToolStrip() tsBottom.Items.Add("Bottom") tspBottom.Join(tsBottom) ' Create the "Right" ToolStrip control and add ' to the corresponding ToolStripPanel. Dim tsRight As New ToolStrip() tsRight.Items.Add("Right") tspRight.Join(tsRight) ' Create the "Left" ToolStrip control and add ' to the corresponding ToolStripPanel. Dim tsLeft As New ToolStrip() tsLeft.Items.Add("Left") tspLeft.Join(tsLeft) ' Create a MenuStrip control with a new window. Dim ms As New MenuStrip() Dim windowMenu As New ToolStripMenuItem("Window") Dim windowNewMenu As New ToolStripMenuItem("New", Nothing, New EventHandler(AddressOf windowNewMenu_Click)) windowMenu.DropDownItems.Add(windowNewMenu) CType(windowMenu.DropDown, ToolStripDropDownMenu).ShowImageMargin = False CType(windowMenu.DropDown, ToolStripDropDownMenu).ShowCheckMargin = True ' Assign the ToolStripMenuItem that displays ' the list of child forms. ms.MdiWindowListItem = windowMenu
69
' Add the window ToolStripMenuItem to the MenuStrip. ms.Items.Add(windowMenu) ' Dock the MenuStrip to the top of the form. ms.Dock = DockStyle.Top ' The Form.MainMenuStrip property determines the merge target. Me.MainMenuStrip = ms ' Add the ToolStripPanels to the form in reverse order. Me.Controls.Add(tspRight) Me.Controls.Add(tspLeft) Me.Controls.Add(tspBottom) Me.Controls.Add(tspTop) ' Add the MenuStrip last. ' This is important for correct placement in the zorder. Me.Controls.Add(ms) End Sub ' This event handler is invoked when ' the "New" ToolStripMenuItem is clicked. ' It creates a new Form and sets its MdiParent ' property to the main form. Sub windowNewMenu_Click(ByVal sender As Object, ByVal e As EventArgs) Dim f As New Form() f.MdiParent = Me f.Text = "Form " + Me.MdiChildren.Length.ToString() f.Show() End Sub End Class
[C#] // This code example demonstrates how to use ToolStripPanel // controls with a multiple document interface (MDI). partial class Form1 : Form { public Form1() { //Make the Form an MDI parent. this.IsMdiContainer = true; //Create ToolStripPanel controls. ToolStripPanel tspTop = new ToolStripPanel(); ToolStripPanel tspBottom = new ToolStripPanel(); ToolStripPanel tspLeft = new ToolStripPanel(); ToolStripPanel tspRight = new ToolStripPanel(); //Dock the ToolStripPanel controls to the edges of the //form. tspTop.Dock = DockStyle.Top; tspBottom.Dock = DockStyle.Bottom; tspLeft.Dock = DockStyle.Left; tspRight.Dock = DockStyle.Right; //Create ToolStrip controls to move among the //ToolStripPanel controls. //Create the "Top" ToolStrip control and add //to the corresponding ToolStripPanel. ToolStrip tsTop = new ToolStrip(); tsTop.Items.Add("Top");
70
tspTop.Join(tsTop); //Create the "Bottom" ToolStrip control and add //to the corresponding ToolStripPanel. ToolStrip tsBottom = new ToolStrip(); tsBottom.Items.Add("Bottom"); tspBottom.Join(tsBottom); //Create the "Right" ToolStrip control and add corresponding ToolStripPanel. ToolStrip tsRight = new ToolStrip(); tsRight.Items.Add("Right"); tspRight.Join(tsRight);
//to the
//Create the "Left" ToolStrip control and add //to the corresponding ToolStripPanel. ToolStrip tsLeft = new ToolStrip(); tsLeft.Items.Add("Left"); tspLeft.Join(tsLeft); //Create a MenuStrip control with a new window. MenuStrip ms = new MenuStrip(); ToolStripMenuItem windowMenu = new ToolStripMenuItem("Window"); ToolStripMenuItem windowNewMenu = new ToolStripMenuItem("New", null, new EventHandler(windowNewMenu_Click)); windowMenu.DropDownItems.Add(windowNewMenu); ((ToolStripDropDownMenu)(windowMenu.DropDown)).ShowImageMargin = false; ((ToolStripDropDownMenu)(windowMenu.DropDown)).ShowCheckMargin = true; //Assign the ToolStripMenuItem that displays //the list of child forms. ms.MdiWindowListItem = windowMenu; //Add the window ToolStripMenuItem to the MenuStrip. ms.Items.Add(windowMenu); //Dock the MenuStrip to the top of the form. ms.Dock = DockStyle.Top; //The Form.MainMenuStrip property determines the merge //target. this.MainMenuStrip = ms; //Add the ToolStripPanels to the form in reverse order. this.Controls.Add(tspRight); this.Controls.Add(tspLeft); this.Controls.Add(tspBottom); this.Controls.Add(tspTop); //Add the MenuStrip last. //This is important for correct placement in the zorder. this.Controls.Add(ms); } //This event handler is invoked when //the "New" ToolStripMenuItem is clicked. //It creates a new Form and sets its MdiParent //property to the main form. void windowNewMenu_Click(object sender, EventArgs e) { Form f = new Form(); f.MdiParent = this; f.Text = "Form " + this.MdiChildren.Length.ToString(); f.Show();
71
} }
Menu Merging in MDI applications This section describes how menu merging works in MDI applications. Automatic merging Merging in the automatic case is triggered by MDI child activation and deactivation. Upon activation, the MenuStrip in the child form is merged into the MDIParent’s MainMenuStrip. Later with subsequent deactivation/activation pairs as a new form becomes active the last form is unmerged (RevertMerge), then the new form is merged. This behavior can be tweaked via mergeAction property on each ToolStripItem and through the AllowMerge property on MenuStrip. Only MenuStrips participate in automatic merging. To merge ToolStrips, StatusStrip etc, you must merge them manually.
What is the procedure for automatically merging an MDI child menu into a MDI parent? The following procedure discusses how to use automatic merging in an MDI application with MenuStrip. To implement menu merging in MDI applications, there are two things you need to remember to do: 1. Set the MDI parent’s MainMenuStrip property to the MenuStrip on it; 2. Set the Visible property of the MenuStrip on the MDI child form to False; Here is a walkthrough on implementing menu merging in MDI applications. Step 1: Create a Windows Forms application. Form1 is created by default. Make it a MDI parent form by changing its IsMDIContainer property to True. Step 2: Add a MenuStrip (menuStrip1) to Form1. Set Form1’s MainMenuStrip property to menuStrip1. Step 3: Add ToolStripMenuItems to menuStrip1 to look like the following, and leave the menu items’ MergeAction property as Append by default.
72
Step 4: Add a new Form called Form2 to the project, and add a MenuStrip called menuStrip2 to Form2. Set Form2’s MainMenuStrip property to menuStrip2. Step 5: Add a File menu item to menuStrip2 to make it look like the following, and leave the menu items’ MergeAction property as Append by default.
Step 6: Set menuStrip2’s Visible property to False. This is important or otherwise the menuStrip2 will still display on the MDI child form at run time. Step 7: In the MDI parent form (Form1)’s Load event handler, add the following code: Form2 mdiChild = new Form2(); mdiChild.MdiParent = this; mdiChild.Show();
73
Step 8: Run the application. You will see the MDI child’s File menu item is appended to the end of menuStrip1 on the MDI parent form. This is because the MergeAction property of the menu items uses the default Append setting.
To control how the matching menu items are merged, you need to use the MergeAction and MergeIndex properties. You can choose one of the following merge actions:
Member names
Description
Append
Appends the item to the end of the collection, ignoring match results.
Insert
Inserts the item to the target's collection immediately preceding the matched item. A match of the end of the list results in the item being appended to the list. If there is no match or the match is at the beginning of the list, the item is inserted at the beginning of the collection.
MatchOnly
A match is required, but no action is taken. Use this for tree creation and successful access to nested layouts.
Remove
Removes the matched item.
Replace
Replaces the matched item with the source item. The original item's dropdown items do not become children of the incoming item.
Using the steps in the procedure described above, you get different results when you use different combinations of MergeAction and MergeIndex settings:
74
Example 1: On the MDI child form, File menu item: MergeAction = MatchOnly; Save As menu item: MergeAction = Insert, MergeIndex = 4;
Example 2: On the MDI child form, File menu item: MergeAction = Insert, MergeIndex = 1;
Example 3: On the MDI child form, File menu item: MergeAction = MatchOnly; Save As menu item: MergeAction = MatchOnly;
75
Example 4: On the MDI child form, File menu item: MergeAction = Replace;
MDI Window List The Window list in MDI application displays a list of MDI child forms that are open in the application. In the screen shot below, the Window list shows two open MDI child forms on the Windows menu item:
76
You can use the MenuStrip’s MdiWindowListItem property to control the ToolStripMenuItem that is used to display a list of MDI child forms. There are five values you can choose from when you set the MdiWindowListItem property: · editToolStripMenuItem: Use the Edit menu item to display the list of open MDI child windows.
·
fileToolStripMenuItem: Use the File menu item to display the list of open MDI child windows.
77
·
helpToolStripMenuItem: Use the Help menu item to display the list of open MDI child windows.
·
toolsToolStripMenuItem: Use the Tools menu item to display the list of open MDI child windows.
78
·
windowsToolStripMenuItem: Use the Windows menu item to display the list of open MDI child windows.
ToolStripMenuItem.IsMdiWindowListEntry property This property can be used to do post item customization of the MDI window list. This is how you would identify which items are sourced from an MDI child.
79
ToolStrip Rendering or Painting There are several ways to achieve custom painting with the ToolStrip API. As with other System.Windows.Forms.Controls, the ToolStrip and ToolStripItem both have overridable OnPaint methods and Paint events. As with regular painting, the coordinate system is relative to the client area of the control – i.e. the upper left hand corner is 0,0. The Paint event/OnPaint methods for ToolStripItems behave just as regular control paint events. In addition to the Paint event/OnPaint method, the ToolStrip classes implement a rendering scheme that is significantly different from other Windows Forms controls to give finer access to the rendering of the items and container. This is controlled through the ToolStripRenderer class, which has overridable methods for painting the background, item background, item image, item arrow, item text and border of the ToolStrip. The EventArgs for these methods expose quite a few properties (e.g. rectangles, colors, text formats) which can be adjusted as necessary. Rather than custom painting a ToolStrip and the ToolStripItem objects it contains by handling the Paint event for each item, you can easily apply a particular style or theme to a ToolStrip object using the ToolStripRenderer class using one of the following methods: · ·
Set ToolStrip.RenderMode property to one of the ToolStripRenderMode values other than Custom; Set ToolStrip.Renderer property to any class that inherits from the ToolStripRenderer class. This will automatically set the RenderMode.
You can apply the same style to multiple ToolStrip objects in the same application, or to individual ToolStrip objects. The following section discusses the ToolStripRenderer class.
ToolStripRenderer class This class handles the painting functionality for ToolStrip objects. You can use it to easily apply a particular style or theme to a ToolStrip object. Rather than custom painting a ToolStrip and the ToolStripItem objects it contains by overriding their OnPaint methods, you can set the ToolStrip.Renderer property to an object that inherits from ToolStripRenderer. The painting specified by the ToolStripRenderer is applied to the ToolStrip, as well as the items it contains. The ToolStripRenderer class contains the following two stock renderer classes: 1. ToolStripProfessionalRenderer : provides painting functionality for Office look; 2. ToolStripSystemRenderer: offers painting functionality for Internet Explorer appearance; ToolStripRenderer
ToolStripProfessionalRenderer (Office)
ToolStripSystemRenderer (IE)
80
The ToolStripRenderer class provides many Draw* methods to provide full control of the ToolStrip and objects. You can override the OnRender* methods or handle the corresponding rendering events to implement a custom ToolStripRenderer. What order do the ToolStripRenderer events come in? In general, the renderer paints the ToolStrip and objects in the order of background, item background, item foreground effects, ToolStrip border. Specifically, the sequence looks like the following: 1. RenderToolStripBackground 2. RenderImageMargin 3. RenderItemBackground 4. RenderItemImage 5. RenderItemText 6. RenderArrow 7. RenderToolStripBorder The ToolStrip border is painted last, as it's used as the last chance to fix up paint if the items happen to go edge to edge. The ToolStripRender class uses GDI+ to handle the painting of all the elements except for item text. Measuring and drawing text is done through the new TextRenderer class which is based on GDI technology.
How do I implement a custom ToolStripRenderer? You can customize the appearance of a ToolStrip control by implementing a class that derives from ToolStripRenderer. This gives you the flexibility to create an appearance that differs from the appearance provided the ToolStripProfessionalRenderer and ToolStripSystemRenderer classes. There are two steps involved: Derive a custom class from ToolStripRenderer class and override the OnRender* methods. Step 1: Derive a custom class from the ToolStripRenderer, ToolStripProfessionalRenderer or ToolStripSystemRenderer class: [VB] Class CustomProfessionalRenderer Inherits ToolStripProfessionalRenderer ' Add your implementation here End Class
[C#] class CustomProfessionalRenderer : ToolStripProfessionalRenderer { { // Add your implementation here }
Step 2: Override the OnRender* methods to customize the painting. [VB] ' This sample type demonstrates a custom renderer. It overrides the ' OnRenderMenuItemBackground and OnRenderButtonBackground methods ' to customize the backgrounds of MenuStrip items and ToolStripbuttons.
81
Class CustomProfessionalRenderer Inherits ToolStripProfessionalRenderer Protected Overrides Sub OnRenderMenuItemBackground(ByVal e As ToolStripItemRenderEventArgs) ' Add your implementation here End Sub Protected Overrides Sub OnRenderButtonBackground(ByVal e As ToolStripItemRenderEventArgs) ' Add your implementation here End Sub ' Override more OnRender* methods as you like End Class
[C#] // This sample type demonstrates a custom renderer. It overrides the // OnRenderMenuItemBackground and OnRenderButtonBackground methods // to customize the backgrounds of MenuStrip items and ToolStripbuttons. class CustomProfessionalRenderer : ToolStripProfessionalRenderer { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { // Add your implementation here } protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) { // Add your implementation here } // Override more OnRender* methods as you like }
Note: for accessibility concerns, use standard system colors and disable extraneous images while in high contrast mode (SystemInformation.HighContrast is true).
How do I globally change the painting (Renderer) for all my ToolStrips? You need to do the following: 1. Use RenderMode to pick between stock renderers. 2. Use ToolStrip.Renderer to assign a custom renderer. 3. Ensure that RenderMode is set to ManagerRenderMode (default) class Form6 : Form { ComboBox targetComboBox = new ComboBox(); public Form6() { // alter renderer at top level // new toolstrip ToolStrip ts = new ToolStrip(); ts.Name = "ToolStrip"; ts.Items.Add("Apples");
82
ts.Items.Add("Oranges"); ts.Items.Add("Pears"); // new menustrip, with new window MenuStrip ms = new MenuStrip(); ms.Name = "MenuStrip"; ms.Dock = DockStyle.Top; // add top level items ToolStripMenuItem fileMenuItem = new ToolStripMenuItem("File"); ms.Items.Add(fileMenuItem); ms.Items.Add("Edit"); ms.Items.Add("View"); ms.Items.Add("Window"); // add subitems to "File" fileMenuItem.DropDownItems.Add("Open"); fileMenuItem.DropDownItems.Add("Save"); fileMenuItem.DropDownItems.Add("Save As..."); fileMenuItem.DropDownItems.Add(""); fileMenuItem.DropDownItems.Add("Exit"); // Add button to apply renderers Button applyButton = new Button(); applyButton.Text = "Apply Custom Renderer"; applyButton.Click += new EventHandler(applyButton_Click); // Add combobox targetComboBox.Items.Add("All"); targetComboBox.Items.Add("MenuStrip"); targetComboBox.Items.Add("ToolStrip"); targetComboBox.Items.Add("Reset"); applyButton.Click += new EventHandler(applyButton_Click); // Add TLP TableLayoutPanel tlp = new TableLayoutPanel(); tlp.Dock = DockStyle.Fill; tlp.RowCount = 1; tlp.ColumnCount = 2; tlp.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent)); tlp.Controls.Add(applyButton); tlp.Controls.Add(targetComboBox); // Add groupbox GroupBox gb = new GroupBox(); gb.Text = "Apply Renderers"; gb.Dock = DockStyle.Fill; gb.Controls.Add(tlp); // Add groupbox to form this.Controls.Add(gb); // Add toolstrip to controls collection this.Controls.Add(ts); // Add menustrip to controls collection last Z order! this.Controls.Add(ms); } void applyButton_Click(object sender, EventArgs e) {
83
ToolStrip ms = ToolStripManager.FindToolStrip("MenuStrip"); ToolStrip ts = ToolStripManager.FindToolStrip("ToolStrip"); switch (targetComboBox.SelectedItem.ToString()) { case "Reset": ms.RenderMode = ToolStripRenderMode.ManagerRenderMode; ts.RenderMode = ToolStripRenderMode.ManagerRenderMode; // default ToolStripManager.RenderMode = ToolStripManagerRenderMode.Professional; break; case "All": ms.RenderMode = ToolStripRenderMode.ManagerRenderMode; ts.RenderMode = ToolStripRenderMode.ManagerRenderMode; // default ToolStripManager.Renderer = new CustomProfessionalRenderer(); break; case "MenuStrip": ms.Renderer = new CustomProfessionalRenderer(); break; case "ToolStrip": ms.Renderer = new CustomProfessionalRenderer(); break; } } void ChangeColors_Click(object sender, EventArgs e) { ToolStripManager.Renderer = new CustomProfessionalRenderer(); } } class CustomProfessionalRenderer : ToolStripProfessionalRenderer { protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Selected) { using (Brush b = new SolidBrush(ProfessionalColors.SeparatorLight)) { e.Graphics.FillEllipse(b, e.Item.ContentRectangle); } } else using (Pen p = new Pen(ProfessionalColors.SeparatorLight)) { e.Graphics.DrawEllipse(p, e.Item.ContentRectangle); } } protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) { Rectangle r = Rectangle.Inflate(e.Item.ContentRectangle, 2, 2); if (e.Item.Selected)
84
{ using (Brush b = new SolidBrush(ProfessionalColors.SeparatorLight)) { e.Graphics.FillRectangle(b, r); } } else using (Pen p = new Pen(ProfessionalColors.SeparatorLight)) { e.Graphics.DrawRectangle(p, r); } } }
When should I use Paint/OnPaint and when should I override the ToolStripRenderer? If you want to tweak a few aspects of how an item is painted, overriding the ToolStripRenderer might be the right idea. If you are writing a new item and want to control all aspects of the painting, overriding OnPaint will give you total control. From the OnPaint, you can use methods from the ToolStripRenderer by calling Owner.Renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(e)); Do I need to worry about double buffering? By default the ToolStrip is double buffered; taking advantage of the OptimizedDoubleBuffer API offered in Windows Forms 2.0. How do I turn off the "Office" colors? For one ToolStrip · · ·
ProfessionalColorTable colorTable = new ProfessionalColorTable(); colorTable.UseSystemColors = true; toolStrip.Renderer = new ToolStripProfessionalRenderer(colorTable);
For the entire app ToolStripManager.VisualStylesEnabled = false;
Can I make the ProfessionalRenderer look like the old office? Yes. You need to take the following steps: 1. Create a class which overrides the ToolStripProfessionalRenderer called OldProfessionalRenderer; 2. Pass in a new ProfessionalColorTable with professionalColorTable.UseSystemColors = false; 3. In the OldProfessionalRenderer class, override the following methods:
85
· · ·
OnRenderImageMargin (clear with ControlLight), OnRenderBorder (do nothing), OnRenderToolStripBackground (clear with ControlLight).
ToolStripProfessionalRenderer class This class inherits from ToolStripRender class and provides the Microsoft Office look and feel to your application. When the operating system uses XP Visual style, using this class applies a bluetoned, olive green, or silvertoned palette depending on the operating system color scheme selected by the user. When the operating system uses the Windows Classic style, then this class applies the classic look and feel to the application. This class exposes two properties described in the table below: Property names
Description
ColorTable
Gets an instance of the ProfessionalColorTable class, which provides color palette used for Office display elements.
RoundedEdges
Indicates whether edges of controls have a rounded rather than a square or sharp appearance. This is regardless whether the OS uses the Windows Class style or the XP Visual style. OS uses XP Visual Style ToolStrip has square edges when it uses the professional render and the Renderer’s RoundedEdges is set to False:
ToolStrip has square edges when it uses the professional render and the Renderer’s RoundedEdges is set to True:
OS uses Windows Class Visual Style ToolStrip has square edges when it uses the professional render and the Renderer’s RoundedEdges is set to False:
ToolStrip has square edges when it uses the professional render and the Renderer’s RoundedEdges is set to True:
86
How to create a Professionally Styled ToolStrip Control? You can give your application’s ToolStrip controls a professional appearance and behavior (with Microsoft Office look and feel) by writing your own class derived from the ToolStripProfessionalRenderer class. Step 1: Derive a custom professional renderer class from ToolStripProfessionalRenderer class. [C#] internal class CustomProfessionalRenderer : ToolStripProfessionalRenderer { //Override the OnRender* methods to implement custom professional rendering }
[VB] Friend Class CustomProfessionalRenderer Inherits ToolStripProfessionalRenderer 'Override the OnRender* methods to implement custom professional 'rendering End Class
Step 2: Set the Toolstrip’s Renderer to an instance of the new custom professional renderer. [C#] CustomProfessionalRenderer cpr = new CustomProfessionalRenderer(); this.toolStrip1.Renderer = cpr;
[VB] Dim cpr As CustomProfessionalRenderer = New CustomProfessionalRenderer Me.ToolStrip1.Renderer = cpr
How do I change the ProfessionalColorTable? You need to override ProfessionalColorTable and change only the colors you care about. Professional Colors Sample1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load Dim t As MyColorTable = New MyColorTable ToolStrip1.Renderer = New ToolStripProfessionalRenderer(t) End Sub
Class MyColorTable Inherits ProfessionalColorTable
Public Overrides ReadOnly Property ButtonPressedGradientBegin() As Color Get Return Color.FromArgb(147, 210, 254) End Get End Property
87
Public Overrides ReadOnly Property ButtonPressedGradientMiddle() As System.Drawing.Color Get Return Color.FromArgb(83, 132, 252) End Get End Property
Public Overrides ReadOnly Property ButtonPressedGradientEnd() As System.Drawing.Color Get Return Color.FromArgb(18, 55, 250) End Get End Property
Public Overrides ReadOnly Property ButtonSelectedGradientBegin() As Color Get Return Color.FromArgb(204, 227, 255) End Get End Property
Public Overrides ReadOnly Property ButtonSelectedGradientMiddle() As System.Drawing.Color Get Return Color.FromArgb(160, 199, 255) End Get End Property
Public Overrides ReadOnly Property ButtonSelectedGradientEnd() As System.Drawing.Color Get Return Color.FromArgb(116, 171, 255) End Get End Property End Class
Professional Colors Sample2 Below is an example of custom Professional Colors with builtin ProfessionalRenderer and setting Renderer at runtime. class Form2 : Form { public Form2() { // new toolstrip ToolStrip ts = new ToolStrip(); ts.Items.Add("Apples"); ts.Items.Add("Oranges"); ts.Items.Add("Pears"); ts.Items.Add("Change Colors", null, new EventHandler(ChangeColors_Click)); // new menustrip, with new window MenuStrip ms = new MenuStrip(); ms.Dock = DockStyle.Top;
88
// add top level items ms.Items.Add("File"); ms.Items.Add("Edit"); ms.Items.Add("View"); ms.Items.Add("Window"); // Add toolstrip to controls collection this.Controls.Add(ts); // Add menustrip to controls collection last Z order! this.Controls.Add(ms); } void ChangeColors_Click(object sender, EventArgs e) { ToolStripManager.Renderer = new ToolStripProfessionalRenderer(new CustomProfessionalColors()); } } class CustomProfessionalColors : ProfessionalColorTable { public override Color ToolStripGradientBegin { get { return Color.BlueViolet; } } public override Color ToolStripGradientMiddle { get { return Color.CadetBlue; } } public override Color ToolStripGradientEnd { get { return Color.CornflowerBlue; } } public override Color MenuStripGradientBegin { get { return Color.BlueViolet; } } public override Color MenuStripGradientEnd { get { return Color.CornflowerBlue; } } }
How to I paint the connected Area? Connected area is that little bit of the dropdown for a menu where the border is discontinuous. Below is an example of how to access and paint that. protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) { using (Brush b = new SolidBrush(ColorTable.MyBackgroundColor)) { e.Graphics.FillRectangle(b, e.ConnectedArea); } }
How do I change text color on selection? Below is an example of changing text color on selection within a custom renderer: protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) { if (e.Item.Selected) {
89
e.TextColor = Color.Gold; } else { e.Item.ForeColor = Color.White; } base.OnRenderItemText(e); }
How can I get the office look and feel to have straight ends?
Set RoundedEdges = false. You may also have to override OnRendererToolStripBorder and not to call the base. ((ToolStripProfessionalRenderer)ToolStripManager.Renderer).RoundedEdges = false;
ToolStripSystemRender class This class inherits from ToolStripRenderer class and provides the appearance and style of IE. By default, the ToolStripSystemRenderer applies a palette of SystemColors and visual styles, if visual styles are enabled for the application. The following figures show the appearance of the ToolStrip rendered with ToolStripSystemRenderer on systems with Windows Classic style and XP Visual style: On OS with Windows Classic style
On OS with XP Visual style
90
You can also customize the ToolStripSystemRenderer in the same way used to customize the ToolStripProfessionalRenderer class. The two same steps are involved: Step 1: Derive a custom system renderer class from ToolStripSystemRenderer class. Step 2: Set the Toolstrip’s Renderer to an instance of the new custom system renderer.
ToolStrip’s RenderMode property Besides using the ToolStripRenderer (ToolStripProfessionalRenderer, ToolStripSystemRenderer) to control the rendering of the ToolStrip controls, you can also use the ToolStrip’s RenderMode property to control whether the application is painted by the ToolStripProfessionalRenderer, the ToolStripSystemRenderer, or a customized ToolStripRenderer. It can be one of the following values: Setting
Description
Custom
You cannot explicitly set the ToolStrip.RenderMode to Custom. However, the ToolStrip.RenderMode returns Custom when the ToolStrip.Renderer is set to an extension of the ToolStripRenderer class that is not ToolStripProfessionalRenderer or ToolStripSystemRenderer.
System
The painting is done using ToolStripSystemRenderer to provide the IE look and feel;
Professional
The painting is done using ToolStripProfessionalRenderer to provide Office look and feel;
MangerRenderMode (default)
The painting style is determined by ToolStripManager.RenderMode property or ToolStripManager.Renderer property; The ToolStrip control uses this setting by default.
ToolStripManager’s RenderMode and Renderer properties As discussed earlier in the training, the ToolStripManager class can be used together with the ToolStripRenderer class to gain even more control and customizability over painting of ToolStrip. ToolStripManager’s RenderMode property The ToolStripManager’s RenderMode property sets the painting style for multiple ToolStrip objects on a form that have their ToolStrip.RenderMode property set to ToolStripRenderMode.ManagerRenderMode. It can have one of the ToolManagerRenderMode values: Setting
Description
Custom
You cannot explicitly set the ToolStripManager.RenderMode to Custom. However, the ToolStripManager.RenderMode returns Custom
91
when the ToolStripManager.Renderer is set to an extension of the ToolStripRenderer class that is not ToolStripProfessionalRenderer or ToolStripSystemRenderer. System
The painting is done using ToolStripSystemRenderer to provide the IE look and feel;
Professional
The painting is done using ToolStripProfessionalRenderer to provide Office look and feel;
ToolStripManager.Renderer property ToolStripManager,Renderer property is used when the RenderMode property of the current ToolStrip is set to ManagerRenderMode. You can use this property to apply a custom renderer at the application level. For example, you have implemented a custom ToolStripRenderer class named CustomRenderer and would like to use it to render all ToolStrip controls at the application level. You can simply assign the ToolStripManager’s Renderer property to an instance of the CustomRenderer class, and make sure that ToolStrip.RenderMode is set to the default value of ManagerRenderMode: ToolStripManager.Renderer = New CustomRenderer()
92