Sei sulla pagina 1di 45

ToolStrips and Related Controls (Strip Controls)

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.

About this document:


This material should be neither be considered a complete coverage of ToolStrips nor a deep dive into
any one area. It simply tries to capture common talking points, interesting elements and answer
common questions.

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.

1.1 Object Heirarchy

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));

Q: 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.

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.

1.4 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, 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.

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;

1.7 Flow from parent to auto created dropdowns


For the implementation of faux-ambient 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


Refers to instancing a ToolStripDropDown, ToolStripDropDownMenu or ContextMenuStrip, populating it,
then assigning to a ToolStripDropDownItem’s DropDown property:

Implicit (automatic) creation of ToolStripDropDown


Refers to populating a ToolStripDropDownItem’s DropDownItems collection. When that item is
activated, the dropdown in created by use containing 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");
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);

1.8 Image scaling


Image scaling is determined by the interaction of several properties.

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.

Q: How do I get one image out of many to not be scaled?


A: Use ToolStripItem.ImageScaling = ToolStrimItemImageScaling.None

1.9 Designtime Customization


The two avenues of customization covered here are custom ToolStripItems at design time and custom
renderer custom ToolStrips at design time.

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.

// this extends ToolStripButton


// note: visibility from base class preserved
public class myFirstToolStripButton : ToolStripButton { }

// this adds visibility into MenuStrip


// ToolStrip, ContextMenuStrip, StatusStrip also supported
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.MenuStrip |
ToolStripItemDesignerAvailability.ToolStrip)]
public class myOtherToolStripButton : ToolStripButton { }

// this adds a custom bitmap


[ToolboxBitmap(typeof(myNextToolStripButton), "myNextToolStripButton.bmp")]
public class myNextToolStripButton : ToolStripButton { }

// this adds custom toolbox item attributes


[ToolboxItem(typeof(CustomControlToolboxItem))]
public class myLastToolStripButton : ToolStripButton { }

public class CustomControlToolboxItem : ToolboxItem


{
public CustomControlToolboxItem() { }
public override void Initialize(Type type)
{
base.Initialize(type);
this.DisplayName = "My Last ToolStrip Button";
this.Bitmap = new Bitmap(typeof(CustomControlToolboxItem),
"myLastToolStripButton.bmp");
}}

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.

Sample: CustomToolStrip @ DesignTime


public class myToolStrip : ToolStrip
{
public myToolStrip()
{
Renderer = new myToolStripRenderer();
}
}
public class myToolStripRenderer : ToolStripProfessionalRenderer
{
public myToolStripRenderer()
: base(new myProfessionalColors())
{
}
}
public class myProfessionalColors : ProfessionalColorTable
{
public override Color ToolStripGradientBegin
{
get { return Color.HotPink; }
}

public override Color ToolStripGradientEnd


{
get { return Color.Salmon; }
}

public override Color ToolStripGradientMiddle


{
get { return Color.Orange; }
}
}

1.10 Customization Dialog


A common customer request we get is a dialog similar to Office’s to handle end user customization to
choose items. We don’t include this in the product. However, we do have a great sample on this
already created, and the API around ToolStrips is simple enough, we feel creating one of these on your
own isn’t a monumental task.

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.

Sample is here: http://blogs.msdn.com/jfoscoding/articles/477104.aspx


2 ToolStrip
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.

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.

Features notes with StackLayouts


 ToolStripItem.Alignment controls which side of the ToolStrip the item is aligned to.
 ToolStripItem.Overflow controls whether an item can overflow to the ToolStripOverflow
dropdown Always, AsNeeded, or Never.
 When items do not fit within the ToolStrip, an Overflow button is rendered. Additional items
appear in the ToolStripOverflow dropdown.
 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).
 A ToolStrip can be “movable” if it is placed in a ToolStripPanel and it’s GripStyle is set to
Visible.

Non-Stack layouts
Flow

Default for ContextMenuStrip/ToolStripDropDownMenu/ToolStripOverflow, very similar to the


FlowLayoutPanel.

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.

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; }
}

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.

For StatusStrip, all “Spring” columns are set to 100%, all other columns are set to AutoSize in an
overridable method called OnSpringTableLayoutCore.

Q: How do I change layout characteristics not dircectly exposed in ToolStrip?


You access the LayoutSettings object offered at the ToolStripLevel 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?


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;
}
}
}
}

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: Image usage is demonstrated in several SDK samples.


TextImageRelation
ToolStripItem exposes a TextImageRelation property that defines the relative placement of the Image
with respect to the Text. It special cases image null or empty text and lays those items out without
having a “blank” spot for the missing element.

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.

How can I tell when the mouse is over 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.

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.

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;
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;
}
}

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.

Q: 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.

Q: 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.

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.

How do I get toggle button?


toolStripButton.CheckOnClick = true;
toolStripButton.CheckedChanged += new EventHandler(toolStripButton_CheckedChanged);

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.

Q: Does ToolStrips automatically eliminate duplicate or trailing separators from


layout?
Nope, but the following code will do it for you:

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;
}
}
}
}

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.

toolStrip1.Items.Add(new ToolStripControlHost(new TrackBar()));

Sample showing 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
}

}
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;

// set other defaults that are interesting


protected override Size DefaultSize {
get {
return new Size(200, 16);
}
}

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.

NOTE: See http://blogs.msdn.com/jfoscoding/archive/2005/03/03/384430.aspx for sample how to


replace a ComboBox dropdown with a ToolStripDropDown.

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.

// 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);

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.

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
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;
}

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.

AutoToolTip is set to true for ToolStripButton, ToolStripDropDownButton, ToolStripSplitButton


NOTE: If (AutoToolTip) and (ToolTipText is empty) use the Text property to display as ToolTip(Text is
stripped of ampersand characters which would represent mnemonics Text="&File" yields a toolTip of
"File")

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.

NOTE: There is an SDK sample on dynamic DisplayStyle as an alternative to Overflow.

Dynamic Overflow sample


The following 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());
}
}

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
{

ContextMenuStrip cms = new ContextMenuStrip();


ToolStrip toolstrip = new ToolStrip();
ToolStripButton placeholder = new ToolStripButton();

ToolStripItem[] originalItemCollection;

public Form1()
{
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);

// turn overflow button on


placeholder.Available = true;
}
}
}
cms.ResumeLayout(false);
toolstrip.ResumeLayout(true);

}
}
}

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.

1. Create the MDI parent form as usual, setting MainForm.IsMdiContainer = true.


2. Add a MenuStrip to the MDI parent, setting MainForm.MainMenuStrip = menuStrip1
3. Create an MDI child form, setting MdiChildForm.MdiParent = MainForm
4. Add a MenuStrip to the MDI child
5. Set the MenuStrip in the MdiChildForm to Visible = false
6. Add menu items to the MdiChildForm that you want to merge into the MainForm’s MainMenuStrip
when the MdiChildForm is activated.
7. Use the MergeAction property on the items in the MdiChild’s MenuStrip to control how the items on
the MDIChildForm merge into the MainForm.

What are the MergeAction values and what do they mean?

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.

How can I get an item aligned to the right?


By default, the StatusStrip is not set to LayoutStyle.StackWithOverfow, therefore the item.Alignment
property is ignored. To align an progress bar to the right, use a ToolStripStatusLabel – set it’s Spring =
true, then add a ToolStripProgressBar. The ToolStripStatusLabel’s text can be set to “” to remove the
text.

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.

4.4 SizingGrip & Grip


There are two different grips on StatusStrip.

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();

// 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)";
}
}
}

4.6 ToolStripStatusLabel Borders


Border control with ToolStripStatusLabels is done via the BorderStyle and BorderSides enums. There is
no built in accomodation to render adjacent ToolStripStatusLabel borders as one.

4.7 Can I show animated images in ToolStrips?


Yes. ToolStrip supports the ImageAnimator class - if you assign an Animated GIF to the Image property
it will automatically render the animation.
5 ContextMenuStrip
ContextMenuStrip is the ToolStrip version of ContextMenu. It can be associated with any control and a
via secondary click will automatically show. It can also be shown programmatically via the Show() API.
It supports an Opening and Closing cancellable events to handle dynamic population and multiclick
scenarios. ContextMenuStrip, like ToolStripDropDown menu is a highly specialized layout supporting
Image, Check, Text, Shortcut and flyout “columns”. It also implements special behavior such as auto
expanding from top level MenuStrip and diagonal submenu access.

5.1 Preferred Items


ToolStripMenuItem - default
ToolStripSeparator
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.

ContextMenuStrip Sample
ContextMenuStrip.Opening
e.Cancel handling with no items
Dynamic SourceControl determination w/ reuse
Dynamic item addition

class Form3 : Form


{
private ContextMenuStrip fruitContextMenuStrip;

public Form3()
{
// new ContextMenuStrip
fruitContextMenuStrip = new ContextMenuStrip();

// sync opening event


fruitContextMenuStrip.Opening += new
System.ComponentModel.CancelEventHandler(cms_Opening);

// 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;

// new MenuStrip
MenuStrip ms = new MenuStrip();
ToolStripMenuItem fruitToolStripMenuItem = new ToolStripMenuItem("Fruit", null,
null, "Fruit");
ms.Items.Add(fruitToolStripMenuItem);
ms.Dock = DockStyle.Top;

// wire up ToolStripMenuItem DropDown


fruitToolStripMenuItem.DropDown = fruitContextMenuStrip;

// wire up Form ContextMenuStrip


this.ContextMenuStrip = fruitContextMenuStrip;

// Add the toolstrip to the controls collection


this.Controls.Add(ts);

// add menustrip to the controls collection last - Z order!


this.Controls.Add(ms);
}

void cms_Opening(object sender, System.ComponentModel.CancelEventArgs e)


{
// grab owners
Control c = fruitContextMenuStrip.SourceControl as Control;
ToolStripDropDownItem tsi = fruitContextMenuStrip.OwnerItem as
ToolStripDropDownItem;

// clear collection
fruitContextMenuStrip.Items.Clear();

// check source control first


if (c != null)
{
// Add custom item (Form)
fruitContextMenuStrip.Items.Add("Source: " + c.GetType().ToString());
}
else if (tsi != null)
{
// Add custom item (ToolStripDropDownButton or ToolStripMenuItem)
fruitContextMenuStrip.Items.Add("Source: " + tsi.GetType().ToString());
}

// add default items


fruitContextMenuStrip.Items.Add("-");
fruitContextMenuStrip.Items.Add("Apples");
fruitContextMenuStrip.Items.Add("Oranges");
fruitContextMenuStrip.Items.Add("Pears");

// set cancel to false (optimized to true based on empty entry)


e.Cancel = false;

}
}

5.2 Dynamic population of DropDown on show()


There is an SDK sample that shows this in conjunction with reusing a ContextMenuStrip across multiple
controls.

5.3 How do I prevent a dropdown from closing?


Two ways, set AutoClose = false, or handle the Closing event and set e.Cancel = true. The Closing
event should give you a reason - 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.

5.4 Dynamic dropdown sample

How do I dynamically populate a dropdown in the Opening event?

How do I dynamically show a dropdown for my form?


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


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);
}
}
}

5.5 Image and Check Margins


enable/disable check margin
enable/disable image margin
check rendering (image, no image)
raw Bitmap creation
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;

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;

}
}

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

5.7 How can I make a user resizable dropdown?


Handle WM_NCHITTEST. See http://blogs.msdn.com/jfoscoding/archive/2005/04/20/410231.aspx for
more detail.

5.8 ToolStripDropDown as a Tree-View dropdown


This is a rather spiffy article: http://blogs.msdn.com/jfoscoding/archive/2005/03/03/384430.aspx
6 ToolStripManager
ToolStripManager is a static class that handles application wide ToolStrip related tasks such as merging,
settings and renderer exposure.

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.

See also section 1.3

Manual
Manual merging is accomplished by calling ToolStripManager.Merge() and RevertMerge().

Q: Why is there an empty MenuStrip in my child MDI forms?


The MenuStrip is visible=true and even though it is empty, we render it. Simply set Visible=false to fix
this.

Q: What does MatchOnly do?


A MergeAction of MatchOnly simply provides a mechanism to navigate through the menu structure
without taking any true action. In a way it provides a path to evaluate the subsequent items.

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");

// set top level item to MatchOnly


veggieMenuStripItem2.MergeAction = MergeAction.MatchOnly;
// set all child items to insert at 1 (zero based)
// insert between Asparagus and Jicama
foreach (ToolStripMenuItem tsmi in veggieMenuStripItem2.DropDownItems)
{
tsmi.MergeAction = MergeAction.Insert;
tsmi.MergeIndex = 1;
}

// do this on activation or focus


ToolStripManager.Merge(veggieMenuStrip2, veggieMenuStrip);

this.Controls.Add(veggieMenuStrip);

Q: Do you have a sample with the other MergeActions?


See http://blogs.msdn.com/jfoscoding/articles/472113.aspx

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.

private void Form1_Load(object sender, EventArgs e)


{
// load and apply settings last saved
ToolStripManager.LoadSettings(this);
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)


{
// Save out current state of ToolStrips
ToolStripManager.SaveSettings(this);
}

Q: Ok, so how about providing a way to reset the settings?


A: The sample code below will do that – it simply uses a named set of settings that captures the state
before any custom settings are applied. Then, with button click or whatever you can apply the custom
set.

private void Form1_Load(object sender, EventArgs e)


{
// save out a snapshop of init component
ToolStripManager.SaveSettings(this, "RESET");

// load and apply settings last saved


ToolStripManager.LoadSettings(this);
}

private void newToolStripMenuItem_Click(object sender, EventArgs e)


{
// apply the RESET settings
ToolStripManager.LoadSettings(this, "RESET");
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)


{
// Save out current state of ToolStrips
ToolStripManager.SaveSettings(this);
}
7 ToolStripRenderer

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

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");
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)


{
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)
{
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.2 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;

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*.

public class MyLabel : ToolStripLabel{


protected override void OnPaint(PaintEventArgs e) {

// Advantage here is that you’d get free disabled image support


this.Parent.Renderer.DrawItemImage(new
ToolStripItemImageRenderEventArgs(e.Graphics, this, this.Image, this.Bounds));

}
}
8 ToolStripProfessionalRenderer

8.1 What order do the ToolStrip Renderer events come in?


Generally its this - background, item background, item foregound effects, toolstrip border.
 OnRenderToolStripBackground
 OnRender[Label|Button|MenuItem...]Background
 OnRenderItemText
 OnRenderItemArrow
 OnRenderItemImage
 OnRenderToolStripBorder
The toolstrip border is painted last, as it's sort of a last chance fixup paint if the items happen to go
edge to edge.

8.2 ProfessionalColors

How do I change the ProfessionalColorTable?


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

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 w/ built in 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;

// 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; } }
}

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.

protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)


{
using (Brush b = new SolidBrush(ColorTable.MyBackgroundColor))
{
e.Graphics.FillRectangle(b, e.ConnectedArea);
}
}

8.4 Changing 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)
{
e.TextColor = Color.Gold;
}
else
{
e.Item.ForeColor = Color.White;
}

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.

// 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.

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.

10.1 MDI Support


ToolStripContainer does not support MDI properly because, like any dock filled container, it would be
layered above the MDI child container that is part of the MDI parent. To workaround this, use
ToolStripPanel – see that section for a code example.
11 ToolStripPanel
ToolStripPanel support ToolStrips and allows them to be rearranged dynamically. In addition to this,
ToolStripPanel also provides the drop targetting for cross panel ToolStrip drags.

NOTE: ToolStripPanel is not on the toolbox by default and has a rudimentary design experience.

11.1 MDI Support


The following is how to use ToolStripPanels correctly in an MDIParent. This is important, because due
to layering and MDI limiations, use of ToolStripContainer doesn’t work well.

public Form1()
{
// Make Form MDI Parent
this.IsMdiContainer = true;

// Add toolstrip panels


ToolStripPanel tspTop = new ToolStripPanel();
ToolStripPanel tspBottom = new ToolStripPanel();
ToolStripPanel tspLeft = new ToolStripPanel();
ToolStripPanel tspRight = new ToolStripPanel();

// dock the ToolStripPanels


tspTop.Dock = DockStyle.Top;
tspBottom.Dock = DockStyle.Bottom;
tspLeft.Dock = DockStyle.Left;
tspRight.Dock = DockStyle.Right;

// add toolstrips to move around between the panels


ToolStrip tsTop = new ToolStrip();
tsTop.Items.Add("Top");
tspTop.Join(tsTop);

ToolStrip tsBottom = new ToolStrip();


tsBottom.Items.Add("Bottom");
tspBottom.Join(tsBottom);

ToolStrip tsRight = new ToolStrip();


tsRight.Items.Add("Right");
tspRight.Join(tsRight);

ToolStrip tsLeft = new ToolStrip();


tsLeft.Items.Add("Left");
tspLeft.Join(tsLeft);

// add menustrip, with 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;

ms.MdiWindowListItem = windowMenu;
ms.Items.Add(windowMenu);
ms.Dock = DockStyle.Top;

// Form.MainMenuStrip determines merge target


MainMenuStrip = ms;

// add a button to the MDIClient area


Button b = new Button();
b.AutoSize = true;
b.Text = "In the MDI Container";

// 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 menustrip last - Z order!


this.Controls.Add(ms);

void windowNewMenu_Click(object sender, EventArgs e)


{
Form f = new Form();
f.MdiParent = this;
f.Text = "Form - " + this.MdiChildren.Length.ToString();
f.Show();

}
}

11.2 How do I programatically 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.

Potrebbero piacerti anche