Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
The ToolStrip family of controls provides and common interface for producing user interface elements
for Windows Forms. It fully replaces MainMenu, ContextMenu, StatusBar and ToolBar with a windowless
control architecture. In addition to replacing these controls, it provides a common rendering model,
extensibility options, parallel UI across containers and supporting utility functions and usage controls.
This document is divided into about 11 sections starting with a general section, followed by control
based sections wrapped up by a samples area.
Contents
1 Strip Controls..................................................................................................... 3
1.1 Object Heirarchy........................................................................................... 3
1.2 Painting...................................................................................................... 3
1.3 Parenting.................................................................................................... 4
1.4 Partial Trust................................................................................................ 4
1.5 Usage........................................................................................................ 5
1.6 Keyboarding................................................................................................. 5
1.7 Flow from parent to auto created dropdowns.........................................................6
1.8 Image scaling............................................................................................... 6
1.9 Designtime Customization................................................................................7
1.10 Customization Dialog......................................................................................8
1.11 Commanding................................................................................................ 8
2 ToolStrip........................................................................................................... 9
2.1 Layout....................................................................................................... 9
2.2 ToolStripItem.............................................................................................. 11
2.3 Cloning..................................................................................................... 12
2.4 ToolStripLabel.............................................................................................13
2.5 ToolStripButton...........................................................................................13
2.6 ToolStripSeparator.......................................................................................13
2.7 ToolStripControlHost()...................................................................................14
2.8 ToolStripTextBox.........................................................................................16
2.9 ToolStripComboBox......................................................................................16
2.10 ToolStripDropDownItem.................................................................................17
2.11 ToolStripDropDownButton...............................................................................17
2.12 ToolStripDropDownButton...............................................................................17
2.13 ToolStripSplitButton......................................................................................18
2.14 ToolTips.................................................................................................... 18
2.15 Alignment.................................................................................................. 19
2.16 Overflow................................................................................................... 19
2.17 AllowItemReorder........................................................................................21
3 MenuStrip........................................................................................................ 22
3.1 ToolStripMenuItem.......................................................................................22
3.2 Stretch..................................................................................................... 22
3.3 MDI.......................................................................................................... 22
4 StatusStrip....................................................................................................... 24
4.1 Layout...................................................................................................... 24
4.2 ToolStripStatusLabel.....................................................................................24
4.3 ToolStripProgressBar.....................................................................................24
4.4 SizingGrip & Grip......................................................................................... 24
4.5 Spring....................................................................................................... 24
4.6 ToolStripStatusLabel Borders...........................................................................25
4.7 Can I show animated images in ToolStrips?...........................................................25
5 ContextMenuStrip...............................................................................................26
5.1 Preferred Items........................................................................................... 26
5.2 Dynamic population of DropDown on show().........................................................27
5.3 How do I prevent a dropdown from closing?..........................................................27
5.4 Dynamic dropdown sample..............................................................................27
5.5 Image and Check Margins................................................................................29
5.6 DropDownDirection.......................................................................................31
5.7 How can I make a user resizable dropdown?.........................................................31
5.8 ToolStripDropDown as a Tree-View dropdown.......................................................31
6 ToolStripManager............................................................................................... 32
6.1 Merging..................................................................................................... 32
6.2 Settings.................................................................................................... 33
7 ToolStripRenderer..............................................................................................35
7.1 How do I globally change the painting (Renderer) for all my ToolStrips?........................35
7.2 How do I turn off the "Office" colors?..................................................................37
7.3 Can I make the ProfessionalRenderer look like the old office?....................................37
7.4 When should I use a renderer and when should I just override OnPaint.........................38
8 ToolStripProfessionalRenderer................................................................................39
8.1 What order do the ToolStrip Renderer events come in?............................................39
8.2 ProfessionalColors........................................................................................39
8.3 ConnectedArea............................................................................................41
8.4 Changing text color on selection.......................................................................41
8.5 How can I get the office look and feel to have straight ends?.....................................41
9 ToolStripSystemRenderer......................................................................................42
10 ToolStripContainer..............................................................................................43
10.1 MDI Support................................................................................................43
11 ToolStripPanel................................................................................................... 44
11.1 MDI Support................................................................................................44
11.2 How do I programatically move ToolStrips within or across ToolStripPanels?...................45
1 Strip Controls
This section includes topics that are broadly applicable across the ToolStrip family of controls.
ToolStrips
ToolStrip:ScrollableControl
MenuStrip
StatusStrip
ToolStripDropDown
ToolStripDropDownMenu
ContextMenuStrip
ToolStripItems
ToolStripItem:Component
ToolStripSeparator
ToolStripButton
ToolStripLabel
ToolStripStatusLabel
ToolStripDropDownItem
ToolStripMenuItem
ToolStripDropDownButton
ToolStripSplitButton
ToolStripControlHost
ToolStripTextBox
ToolStripProgressBar
ToolStripComboBox
ToolStripRenderers
ToolStripRenderer
ToolStripSystemRenderer
ToolStripProfessionalRenderer
Other
ToolStripPanel:ContainerControl
ToolStripContainer:ContainerControl
ToolStripManager (static)
ProfessionalColors (static)
1.2 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 method for
ToolStripItems behave just as regular control paint events.
In addition to the Paint event/OnPaint method, the ToolStrip API gives 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.
Q: 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));
1.3 Parenting
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.
The following lists parenting related properties and an explanation of their use
ToolStripItem ToolStripDropDown.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.
Control ContextMenuStrip.SourceControl
Indentical in function to ContextMenu’s SourceControl. Used to determine which control sourced the
ContextMenuStrip when multiple controls share the same ContextMenuStrip.
ToolStrip ToolStripItem.GetCurrentParent()
Rather than expose r/w Parent, we provide 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 the Overflow.
ToolStrip ToolStripItem.Owner()
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.
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.
1.5 Usage
Toolstrips have three main usage patterns that impact how they are laid out, keyboard interation and
end-user 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.
1.6 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 wihin ToolStrips that attempts to find a matching item based on order of characters in the
Text property.
Shortcuts
Shortcuts used by MenuStrips are different than ShortcutKeys used in MainMenu. One is a precombined
list of keycombinations. MenuStrips simply use a combinations of the Keys enum (not order specific) to
define the shortcut. In addition a provision is made to display a shortcutkey via text (e.g. Delete vs.
Del) via the ShortcutDisplayString
Navigation
Alt activates the MenuStrip pointed to by Form.MainMenuStrip. From there, CTRL+TAB navigates
between ToolStrips within ToolStripPanels. TAB and arrow keys are used to navigate between items in
a ToolStrip. We 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 off 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;
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");
// implicit (automatic)
ToolStripMenuItem veggiesMenuItem = new ToolStripMenuItem("Veggies");
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("Tebuchet MS", 14, FontStyle.Bold);
ms.Items.Add(fruitMenuItem);
ms.Items.Add(veggiesMenuItem);
this.Controls.Add(ms);
size ToolStrip.ImageScalingSize
This is a the size that will be used to scale into as determined by the Item’s ImageScaling and the
container’s AutoSize setting
ToolStripItemImageScaling 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).
ToolStrip ToolStripItem.ImageScalingMode
AutoSize SizeToFit None
No Image Scaling
TRUE Scales to ToolStrip.ImageScalingSize ToolStrip sizes to largest of largest
item or minimum size
No Image Scaling
FALSE Scales to area remaining in ToolStrip
No ToolStrip Sizing
Default in green.
Custom ToolStripItems
Custom ToolStripItems can be created by extending existing ToolStripItems like ToolStripButton or
ToolStripMenuItem – this is very similar to extending any control. To get these showing at design time
and add them to ToolStrips, use the following sample for guidance.
Sample: ToolStripItemDesignerAvailability
This sample shows how to get custom items in the dropdowns used at design time for strip controls. It
requires same named bitmaps to be added to the project as embedded resources.
Custom ToolStrips
Custom ToolStrips are automatically added to the toolbox as are other controls with Whidbey’s new
auto toolbox population. What might not be apparent is using a custom ToolStrip as a vehicle to show
off your custom Renderer and/or colors at designtime. This is simply a design pattern that’s been
useful.
1.11 Commanding
By default, the ToolStrip API does not provide binding. Simple commanding is achievable by
implementing IBindableComponent and databinding to properties on a Command class.
Preferred Items
ToolStripButton - default
ToolStripSeparator
ToolStripLabel
ToolStripDropDownButton
ToolStripSplitButton
ToolStripTextBox
ToolStripComboBox
Preferred items means the items that are designed to render with high accuracy across by system and
professional renderers in all orientations – and those available by default at design time for this
control.
2.1 Layout
By default the ToolStrip control utilizes a StackWithOverflow layout that supports overflow and item
alignment. Stack refers to how the items are laid out within the ToolStrip, each item stacked aside
each other at both ends of the ToolStrip.
ToolStripLayoutStyle ToolStrip.LayoutStyle
Stack layouts
StackWithOverflow
Default for ToolStrip, this ToolStripLayoutStyle automatically alters it’s layout based on the orientation
property of the ToolStrip to handle drag to dock scenarios.
VerticalStackWithOverflow
Just like StackWithOverflow except always renders as vertical.
HorizontalStackWithOverflow
Just like StackWithOverflow except always renders horizontal.
Non-Stack layouts
Flow
Table
Default for StatusStrip, very similar to TableLayoutPanel.
toolStrip.LayoutStyle = ToolStripLayoutStyle.Table;
TableLayoutSettings settings = toolStrip.LayoutSettings as TableLayoutSettings;
settings.RowCount = 12;
public class System.Windows.Forms.TableLayoutSettings :
System.Windows.Forms.LayoutSettings
{
public int ColumnCount { get; set; }
public ColumnStyleCollection ColumnStyles { get; }
public TableLayoutPanelGrowStyle GrowStyle { get; set; }
public int RowCount { get; set; }
public RowStyleCollection RowStyles { get; }
}
For StatusStrip, all “Spring” columns are set to 100%, all other columns are set to AutoSize in an
overridable method called OnSpringTableLayoutCore.
toolStrip1.LayoutStyle = ToolStripLayoutStyle.Flow;
((FlowLayoutSettings)toolStrip1.LayoutSettings).FlowDirection =
FlowDirection.BottomUp;
Dock
ToolStrips have three main usage patterns. One of those is docking within a parent container.
ToolStrips follow the same rules as other Windows Forms controls with regards to docking, except when
Joined into a ToolStripPanel. See ToolStripPanelError: Reference source not found for additional
information.
2.2 ToolStripItem
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.
Image
Images in ToolStrips are supported via direct property set or via ImageList support (runtime only). Also
supported are animated GIFs and .ICO files.
NOTE: The launching shell of the SDK ToolStripSamples sample demonstrates TextImageRelation.
DisplayStyle
DisplayStyle allows you to set values into the Text and Image property, but only display what you want.
This is handy for changing only the display style when showing the same item in a different context. An
example would be showing on the Image in an overflow or quick list.
NOTE: See SDK sample on dynamic display style alteration to handle window resizing.
Available vs Visible
In ToolStrips, Visible always returns the true state of the item and it’s 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 databind against than the Visible property, as the
Visible property also returns the state of it’s container – in the case of a ToolStripDropDown, an item is
usually going to be Visible=false, but Available=true.
2.3 Cloning
By default, ToolStripMenuItem does not contain an implementation for clone. Here's the code for
ToolStripMenuItem.Clone. An alternate solution is to implement IBindableComponent and databind
your menu item to a Command which drives the Text/Image/Enabled/Available properties.
2.4 ToolStripLabel
ToolStripLabel provides label functionality in ToolStrip. 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.
2.5 ToolStripButton
ToolStripButton is the button item for ToolStrips. It is very similar to ToolStripLabel but also supports
depressed rendering, borders, focus, and other key interactions.
2.6 ToolStripSeparator
ToolStripSeparator is rendered as a line or bar in the shipping renderers. It is used to create the look of
grouping and or distinction amongst groups of items.
Q: What’s an easier way to enter a separator than newing one up 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.
2.7 ToolStripControlHost()
This is the base class for our ToolStripTextBox, ToolStripComboBox, ToolStripProgressBar, and can wrap
any user control to be hosted in the ToolStrip. There are multiple ways to use ToolStripControlHost::
Inherit from ToolStripControlHost or use ToolStripControlHost directly.
// show no borders
toolStripDropDown.Renderer = new BorderlessRenderer();
toolStripDropDown.ResumeLayout();
}
private class BorderlessRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
// do nothing
}
}
Creating a wrapper for your ToolStripControlHost
The following sample shows how to wrap a TrackBar by inheriting from ToolStripControlHost. It is
possible to just host the trackbar by these four lines of code:
TrackBar t = new TrackBar();
t.AutoSize = false; // the TrackBar wants to be 45px high by default, turning AutoSize
= false fixes this
t.Height = 16;
toolStrip.Items.Add(new ToolStripControlHost(t));
However, if you want to use the TrackBar in the designer, you'll have to create a wrapper around the
ToolStripControlHost class. The following sample shows how to wrap a property (TrackBar.Value), and
an event (TrackBar.ValueChanged).
[System.ComponentModel.DesignerCategory("code")]
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip |
ToolStripItemDesignerAvailability.StatusStrip)]
public partial class ToolStripTrackBar : ToolStripControlHost {
public ToolStripTrackBar() : base(CreateControlInstance()) {
}
/// <summary>
/// Create a strongly typed property called TrackBar - handy to prevent casting
everywhere.
/// </summary>
public TrackBar TrackBar {
get {
return Control as TrackBar;
}
}
/// <summary>
/// Create the actual control, note this is static so it can be called from the
/// constructor.
///
/// </summary>
/// <returns></returns>
private static Control CreateControlInstance() {
TrackBar t = new TrackBar();
t.AutoSize = false;
t.Height = 16;
// Add other initialization code here.
return t;
}
[DefaultValue(0)]
public int Value {
get { return TrackBar.Value; }
set { TrackBar.Value = value; }
}
/// <summary>
/// Attach to events we want to re-wrap
/// </summary>
/// <param name="control"></param>
protected override void OnSubscribeControlEvents(Control control) {
base.OnSubscribeControlEvents(control);
TrackBar trackBar = control as TrackBar;
trackBar.ValueChanged += new EventHandler(trackBar_ValueChanged);
}
/// <summary>
/// Detach from events.
/// </summary>
/// <param name="control"></param>
protected override void OnUnsubscribeControlEvents(Control control) {
base.OnUnsubscribeControlEvents(control);
TrackBar trackBar = control as TrackBar;
trackBar.ValueChanged -= new EventHandler(trackBar_ValueChanged);
}
/// <summary>
/// Routing for event
/// TrackBar.ValueChanged -> ToolStripTrackBar.ValueChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void trackBar_ValueChanged(object sender, EventArgs e) {
// when the trackbar value changes, fire an event.
if (this.ValueChanged != null) {
ValueChanged(sender, e);
}
}
// add an event that is subscribable from the designer.
public event EventHandler ValueChanged;
2.8 ToolStripTextBox
ToolStripText box is simply the WindowsForms TextBox wrapped in a ToolStripControlHost to make is
hostable via ToolStrips. Some custom renderering of the TextBox is done for border color and size. A
small subset of the properties and events are exposed at the ToolStripTextBox level, but the underlying
TextBox control is fully accessible via ToolStripTextBox.TextBox.
2.9 ToolStripComboBox
ToolStripCombo box is simply the WindowsForms ComboBox wrapped in a ToolStripControlHost to make
is hostable via ToolStrips. Some custom renderering of the ComboBox is done for border color, size and
dropdown arrow. A subset of the hosted control’s properties and events are exposed at the
ToolStripComboBox level, but the underlying ComboBox control is fully accessible via the
ToolStripComboBox.ComboBox property.
2.10 ToolStripDropDownItem
ToolStripDropDownItem is the abstract base class for ToolStripMenuItem, ToolStripDropDownButton,
ToolStripSplitButton and provides the API around populating and synching the dropdown and items
within it.
This class implements all the dropdown plumbing and API including the DropDownItems collection and
DropDown property. This is the base class for ToolStripMenuItem, ToolStripSplitButton, and
ToolStripDropDownButton.
DropDownItemClicked, DropDownItem
You can populate a dropdown via two different methods – either by hydrating the DropDownItems
collection or assigning a created ContextMenuStrip to the ToolStripDropDownItem’s DropDown
property. Another handy feature of ToolStripDropDownItem is the DropDownItemClicked event. This
allows you a handy way to not have to sync each item in a ToolStrip DropDown’s click event. And you
don’t have to fish into the collection either, we just hand you back the item that was clicked on. The
following sample shows these concepts.
// assign a dropdown
ContextMenuStrip cms = new ContextMenuStrip();
cms.Items.Add("Apples");
cms.Items.Add("Bananas");
cms.Items.Add("Cherries");
// menustrip
MenuStrip ms = new MenuStrip();
ms.Items.Add(fruitMenuItem);
ms.Items.Add(veggiesMenuItem);
this.Controls.Add(ms);
2.11 ToolStripDropDownButton
This item renders in a very similar way to ToolStripButton, but shows a dropdown on click. You can
hide or show the DropDownArrow via the ShowDropDownArrow bool.
2.12 ToolStripDropDownButton
Very similar to ToolStripMenuItem from an API standpoint, but renders differently, combining the look
of a button with a dropdown arrow. When clicked a DropDown is shown.
2.13 ToolStripSplitButton
This item renders very similarly to the ToolStripDropDownButton and combines a button side and a
dropdown arrow side. You have full button API combined with DropDown button functionality.
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. This
sample assumes you have a click handler associated with each item in the dropdown and have set a
default item as part of initialilization.
veggieButton.DisplayStyle = ToolStripItemDisplayStyle.Text;
veggieButton.DropDownItemClicked += new
ToolStripItemClickedEventHandler(veggieButton_DropDownItemClicked);
veggieButton.DefaultItemChanged += new EventHandler(veggieButton_DefaultItemChanged);
// menustrip
ToolStrip ts = new ToolStrip();
ts.Items.Add(veggieButton);
this.Controls.Add(ts);
}
2.14 ToolTips
ToolTips are intrinsically supported within ToolStrips. Below lists relevant properties and their affect
on ToolTips.
ToolStrip.ShowItemToolTips
This is to enable ToolTips for the entire ToolStrip. Default is true for ToolStrip, ContextMenuStrip, false
for MenuStrip, StatusStrip.
toolStrip.ShowItemToolTips = true
Text
By default ToolStripItems use the Text property as the textual source for the tooltip content. To alter
this, set AutoToolTip to false.
AutoTooltip
AutoToolTip true directs the ToolStrip to use the Text property as the textual source for the tooltip
content. AutoToolTip false directs the ToolStrip to use the ToolTipText property as the textual source
for the tooltip content.
2.15 Alignment
Alignment is the ability for an item to align itself at one end or the other of the ToolStrip. With this
you can get layouts similar to the main menu in Microsoft Word with the help combo box aligned right.
The alignment property works only when the LayoutStyle of the ToolStrip is set to StackWithOverflow,
HorizontalStackWithOverflow or VerticalStackWithOverflow.
Item layout is done in natural or collection order – the algorithm simply places item in the ToolStrip as
encountered in the Items collection. To programmatically alter where an item is laid out, move the
item in the collection via the toolStrip.Items.Insert() method. Note this will move the item, not
duplicate it.
2.16 Overflow
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.
this.Controls.Add(t);
Custom DropDown
The default Overflow dropdown is available programatically – 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
{
ToolStripItem[] originalItemCollection;
public Form1()
{
InitializeComponent();
// 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");
toolstrip.ResumeLayout();
this.Controls.Add(toolstrip);
toolstrip.OverflowButton.DropDown = cms;
}
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);
}
}
}
2.17 AllowItemReorder
ToolStrips support user customization via ALT+Drag of items. Dragging to reorder only works by default
within the same ToolStrip. Set ToolStrip.AllowItemReorder=true to enable this feature.
3 MenuStrip
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. There are
special MDI features around MDIWindowListItem as well. MenuStrip in this discussion refers to both the
entire tree of MenuStrip, ToolStripMenuItems and the associated dropdowns (ToolStripDropDownMenu)
collectively and to MenuStrip proper (the top level container only).
Preferred Items
ToolStripMenuItem - default
ToolStripTextBox
ToolStripComboBox
Preferred items means the items that are designed to render with high accuracy across by system and
professional renderers in all orientations – and those available by default at design time for this
control.
3.1 ToolStripMenuItem
ToolStripMenuItem is a highly specialized ToolStripDropDownItem that works with
ToolStripDropDownMenu/ContextMenuStrip to handle the special highlighting, layout and columnar
arrangement that is part of menu support.
3.2 Stretch
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 – if Stretch = true, the ToolStrip fills the entire
row, otherwise it sizes as normal.
3.3 MDI
The MDI related features around MenuStrip are described below. Using a MenuStrip in MDI requires
Form.MainMenuStrip to be set in order to identiy 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.
ToolStripMenuItem ToolStrip.MDIWindowListItem
This property identifies the item whose drop down should be populated with the titles of MDI children
associated with this MDI Parent.
ToolStripMenuItem.IsMdiWindowListEntry
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.
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.
NOTE: See the manual merging sections in ToolStripManager section 6.1.
Procedure for automatically merging an MDI child menu into a MDI parent
The following proceedure discusses how to use automatic merging in an MDI application with
MenuStrip.
When thinking about Merging, it is often convenient to describe the action in terms of a target and
source:
Target - this is the ToolStrip you're merging into (e.g. a Main MenuStrip on your form)
Source - this is the ToolStrip with items you want to merge into the Target toolstrip. (e.g. a menu
from an MDI child from)
Merge Action
The merge action should be set on items in the "Source" toolstrip - e.g. your MDI child menu strip.
Append
(default) adds the Source item to the end of the Target Items collection
Insert
adds the Source item to the Target Items collections as specified by the MergeIndex property
set on the Source Item.
Replace
finds a match (using Text property, then MergeIndex if no match), then replaces the matching
Target Item with the Source Item.
(e.g, MDI child item replaces item from MainMenuStrip)
MatchOnly
finds a match (using Text property, then MergeIndex if no match), then adds all the Source
Item's DropDownItems to the Target Item.
(e.g. an MDI child wants to add a menu item to MainMenuStrip's Save As-> menu).
Remove
finds a match (using Text property, then MergeIndex if no match), then removes the item from
the Target ToolStrip.
(e.g. MDI child can remove the save menu item from MainMenuStrip).
Note the usefulness of MatchOnly - it can be used to build up a menu structure to insert/add/remove
into a submenu. The most frequently used MergeActions will be MatchOnly, Append, and Insert.
4 StatusStrip
StatusStrip replaces the StatusBar control. Special features of the StatusBar is a custom Table Layout,
support for the form’s sizing grip and Spring.
4.1 Layout
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.
Preferred Items
ToolStripStatusLabel - default
ToolStripDropDownButton
ToolStripSplitButton
ToolStripProgressBar
Preferred items means the items that are designed to render with high accuracy across by system and
professional renderers in all orientations – and those available by default at design time for this
control.
4.2 ToolStripStatusLabel
ToolStripStatusLabel is a special version of ToolStripLabel designed specifically for use in StatusStrip.
The special features include BorderStyle, BorderSides and Spring.
4.3 ToolStripProgressBar
ToolStripCombo box is simply the WindowsForms ComboBox wrapped in a ToolStripControlHost to make
is hostable via ToolStrips. Some custom renderering of the ComboBox is done for border color, size and
dropdown arrow. A subset of the hosted control’s properties and events are exposed at the
ToolStripComboBox level, but the underlying ComboBox control is fully accessible via the
ToolStripComboBox.ComboBox property.
Grip
Grip 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.
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.
4.5 Spring
Spring is supported only in StatusStrip and only with StatusStripLabels. It utilizes the underlying Table
layout with a columnstyle 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.
Sample
class Form4 : Form
{
ToolStripStatusLabel middleLabel;
public Form4()
{
// new StatusStrip
StatusStrip ss = new StatusStrip();
Preferred items means the items that are designed to render with high accuracy across by system and
professional renderers in all orientations – and those available by default at design time for this
control.
ContextMenuStrip Sample
ContextMenuStrip.Opening
e.Cancel handling with no items
Dynamic SourceControl determination w/ reuse
Dynamic item addition
public Form3()
{
// new ContextMenuStrip
fruitContextMenuStrip = new ContextMenuStrip();
// new ToolStrip
ToolStrip ts = new ToolStrip();
ToolStripDropDownButton fruitToolStripDropDownButton = new
ToolStripDropDownButton("Fruit", null, null, "Fruit");
ts.Items.Add(fruitToolStripDropDownButton);
ts.Dock = DockStyle.Top;
// new MenuStrip
MenuStrip ms = new MenuStrip();
ToolStripMenuItem fruitToolStripMenuItem = new ToolStripMenuItem("Fruit", null,
null, "Fruit");
ms.Items.Add(fruitToolStripMenuItem);
ms.Dock = DockStyle.Top;
// clear collection
fruitContextMenuStrip.Items.Clear();
}
}
public Form1()
{
InitializeComponent();
// add separator
MyContextMenuStrip.Items.Add("-");
// reset flag
CloseClicked = false;
}
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");
// 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;
// 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;
}
return checkImageContextMenuStrip;
}
}
5.6 DropDownDirection
DropDownDirection is controlled via two different mechanisms. One is DefaultDropDownDirection
offered on ToolStrip, the other is an argument to the Show() method on ToolStripDropDownMenu.
TooStrip.DropDownDirection
This controls the default direction that sub dropdowns will be shown, not the dropdown itself.
TooStripDropDownDirection
This enum has members only designed for use in certain situations
These four should be used with Show(). These are positioned absolutely and may overlap existing
dropdowns.
AboveLeft – AboveRight, BelowLeft, BelowRight
These three are for use with Menus and will automatically positioned to not layer over previous
menuse.
Default – use with either, default, respects RightToLeft
Left – use with ToolStripDropDownMenu/ContextMenuStrip, forces left rather than respecting
RightToLeft
Right – use with ToolStripDropDownMenu/ContextMenuStrip, forces right rather than respecting
RightToLeft
6.1 Merging
ToolStripMerging is driven through two different mechanisms: Automatic (MDI) and manual. This
section covers top level concepts in both of the mechanisms. The rules of how the items merge do not
change for these two methods, just the triggering mechanism. MergeActions are evaluated on a per
item live basis – the last one in affects the next. Another key difference between MainMenu merging
and MenuStrip merging is the fact that items are physically moved from one ToolStrip to another rather
than cloned as is the case with MainMenu.
Manual
Manual merging is accomplished by calling ToolStripManager.Merge() and RevertMerge().
Q: How do get items to merge into the middle of a menu, in the right order AND not have
to change an incremental index each time I edit my list of merge items?
There are several factors that contribute to the being a bit tricky. One is the fact that MergeIndex is
ignored when MergeAction = Append. The second is the live nature of the merge; incoming items affect
the index. To accomplish this, order the items in the source merge list in reverse, select them all and
set MergeAction to Insert and MergeIndex to the index of where in the target you want them inserted.
The example below shows a runtime version of this. The result is an alphabetically ordered dropdown.
Code:
// target menustrip
MenuStrip veggieMenuStrip = new MenuStrip();
ToolStripMenuItem veggieMenuStripItem = veggieMenuStrip.Items.Add("Veggies") as ToolStripMenuItem;
veggieMenuStripItem.DropDownItems.Add("Asparagus");
veggieMenuStripItem.DropDownItems.Add("Jicama");
veggieMenuStripItem.DropDownItems.Add("Kale");
// source menustrip
MenuStrip veggieMenuStrip2 = new MenuStrip();
ToolStripMenuItem veggieMenuStripItem2 = veggieMenuStrip2.Items.Add("Veggies") as
ToolStripMenuItem;
veggieMenuStripItem2.DropDownItems.Add("Cauliflower");
veggieMenuStripItem2.DropDownItems.Add("Bok Choy");
this.Controls.Add(veggieMenuStrip);
6.2 Settings
Settings are another feature handled in ToolStripManager. This uses the settings engine to
automatically persist and 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. Add the following code to a form with ToolStrips on it and experiment. Make sure you’ve
named your ToolStrips, they are in ToolStripPanels so they can be moved, and AllowItemReorder is set
to true to enable ALT+drag item shuffling.
7.1 How do I globally change the painting (Renderer) for all my ToolStrips?
Use RenderMode to pick between stock renderers.
Use ToolStrip.Renderer to assign a custom renderer.
Ensure that RenderMode == ManagerRenderMode (default)
Sample
Form 6
Custom Renderer
Setting Renderer per toolstrip
Setting Renderer per application
public Form6()
{
// alter renderer at top level
// new toolstrip
ToolStrip ts = new ToolStrip();
ts.Name = "ToolStrip";
ts.Items.Add("Apples");
ts.Items.Add("Oranges");
ts.Items.Add("Pears");
// Add combobox
targetComboBox.Items.Add("All");
targetComboBox.Items.Add("MenuStrip");
targetComboBox.Items.Add("ToolStrip");
targetComboBox.Items.Add("Reset");
// Add groupbox
GroupBox gb = new GroupBox();
gb.Text = "Apply Renderers";
gb.Dock = DockStyle.Fill;
gb.Controls.Add(tlp);
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;
}
}
if (e.Item.Selected)
{
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);
}
}
7.3 Can I make the ProfessionalRenderer look like the old office?
Yes...
Create a class which overrides the ToolStripProfessionalRenderer called OldProfessionalRenderer
Pass in a new ProfessionalColorTable with professionalColorTable.UseSystemColors = false;
In the OldProfessionalRenderer class, override the following methods:
OnRenderImageMargin (clear with ControlLight),
OnRenderBorder (do nothing),
OnRenderToolStripBackground (clear with ControlLight).
7.4 When should I use a renderer and when should I just override OnPaint
Use draw from custom ToolStrip handler – which is the entry point into Renderer code. OnRender* will
be called as a result. To change Renderer behavior, override OnRender*.
}
}
8 ToolStripProfessionalRenderer
8.2 ProfessionalColors
Class MyColorTable
Inherits ProfessionalColorTable
8.3 ConnectedArea
Connected area is that little bit of the dropdown for a menu where the border is discontinuous. Below
is an examples of how to access and paint that.
base.OnRenderItemText(e);
}
8.5 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 call base.
((ToolStripProfessionalRenderer)ToolStripManager.Renderer).RoundedEdges = false;
9 ToolStripSystemRenderer
The System Renderer renders ToolStrips similar to Win32 look and feel. You can use with or without
VisualStyles by
ToolStripManager.VisualStylesEnabled = false;
10 ToolStripContainer
ToolStrip container is a composite control very similar in overall design to the SplitContainer. It takes
four ToolStripPanels docked to the sides and one ContentPanel dock filled in the middle to make up the
typical four sided arrangment commonly used today. Below are some quick notes on ToolStripContainer
parts.
Sides – ToolStripPanels
The ToolStripPanels on the sides are not removable from the 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.
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.
Expando 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 into the
ToolStripPanels and all other controls parented to the form are reparented to the ContentPanel.
NOTE: ToolStripPanel is not on the toolbox by default and has a rudimentary design experience.
public Form1()
{
// Make Form MDI Parent
this.IsMdiContainer = true;
ms.MdiWindowListItem = windowMenu;
ms.Items.Add(windowMenu);
ms.Dock = DockStyle.Top;
}
}
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.