ToolStrip GTM

55
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

Transcript of ToolStrip GTM

Page 1: ToolStrip GTM

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.

Contents1 Strip Controls...................................................................................................................3

1.1 Object Heirarchy......................................................................................................31.2 Painting....................................................................................................................31.3 Parenting..................................................................................................................41.4 Partial Trust..............................................................................................................41.5 Usage.......................................................................................................................51.6 Keyboarding.............................................................................................................51.7 Flow from parent to auto created dropdowns...........................................................61.8 Image scaling...........................................................................................................61.9 Designtime Customization.......................................................................................71.10 Customization Dialog...............................................................................................81.11 Commanding............................................................................................................8

2 ToolStrip..........................................................................................................................92.1 Layout......................................................................................................................92.2 ToolStripItem..........................................................................................................112.3 Cloning...................................................................................................................122.4 ToolStripLabel........................................................................................................132.5 ToolStripButton......................................................................................................132.6 ToolStripSeparator.................................................................................................132.7 ToolStripControlHost()............................................................................................142.8 ToolStripTextBox....................................................................................................162.9 ToolStripComboBox................................................................................................162.10 ToolStripDropDownItem.........................................................................................172.11 ToolStripDropDownButton......................................................................................172.12 ToolStripDropDownButton......................................................................................172.13 ToolStripSplitButton...............................................................................................182.14 ToolTips..................................................................................................................182.15 Alignment...............................................................................................................192.16 Overflow.................................................................................................................192.17 AllowItemReorder...................................................................................................21

3 MenuStrip......................................................................................................................223.1 ToolStripMenuItem.................................................................................................223.2 Stretch...................................................................................................................223.3 MDI.........................................................................................................................22

4 StatusStrip.....................................................................................................................244.1 Layout....................................................................................................................244.2 ToolStripStatusLabel..............................................................................................244.3 ToolStripProgressBar..............................................................................................24

Page 2: ToolStrip GTM

4.4 SizingGrip & Grip....................................................................................................244.5 Spring.....................................................................................................................244.6 ToolStripStatusLabel Borders.................................................................................254.7 Can I show animated images in ToolStrips?...........................................................25

5 ContextMenuStrip..........................................................................................................265.1 Preferred Items......................................................................................................265.2 Dynamic population of DropDown on show().........................................................275.3 How do I prevent a dropdown from closing?..........................................................275.4 Dynamic dropdown sample....................................................................................275.5 Image and Check Margins......................................................................................295.6 DropDownDirection................................................................................................315.7 How can I make a user resizable dropdown?..........................................................315.8 ToolStripDropDown as a Tree-View dropdown........................................................31

6 ToolStripManager..........................................................................................................326.1 Merging..................................................................................................................326.2 Settings..................................................................................................................33

7 ToolStripRenderer..........................................................................................................357.1 How do I globally change the painting (Renderer) for all my ToolStrips?...............357.2 How do I turn off the "Office" colors?.....................................................................377.3 Can I make the ProfessionalRenderer look like the old office?...............................377.4 When should I use a renderer and when should I just override OnPaint.................38

8 ToolStripProfessionalRenderer.......................................................................................398.1 What order do the ToolStrip Renderer events come in?.........................................398.2 ProfessionalColors..................................................................................................398.3 ConnectedArea.......................................................................................................418.4 Changing text color on selection............................................................................418.5 How can I get the office look and feel to have straight ends?................................41

9 ToolStripSystemRenderer..............................................................................................4210 ToolStripContainer.........................................................................................................43

10.1 MDI Support...........................................................................................................4311 ToolStripPanel................................................................................................................44

11.1 MDI Support...........................................................................................................4411.2 How do I programatically move ToolStrips within or across ToolStripPanels?.........45

Page 3: ToolStrip GTM

1 Strip ControlsThis section includes topics that are broadly applicable across the ToolStrip family of controls.

1.1 Object Heirarchy

ToolStripsToolStrip:ScrollableControlMenuStripStatusStripToolStripDropDownToolStripDropDownMenuContextMenuStrip

ToolStripItemsToolStripItem:ComponentToolStripSeparatorToolStripButtonToolStripLabelToolStripStatusLabelToolStripDropDownItemToolStripMenuItemToolStripDropDownButtonToolStripSplitButtonToolStripControlHostToolStripTextBoxToolStripProgressBarToolStripComboBox

ToolStripRenderersToolStripRendererToolStripSystemRendererToolStripProfessionalRenderer

OtherToolStripPanel:ContainerControlToolStripContainer:ContainerControlToolStripManager (static)ProfessionalColors (static)

1.2 PaintingThere 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

Page 4: ToolStrip GTM

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 ParentingThe 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.OwnerItemOwnerItem 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.SourceControlIndentical 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 TrustThe 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.

Page 5: ToolStrip GTM

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 UsageToolstrips have three main usage patterns that impact how they are laid out, keyboard interation and end-user behavior.

Joined in a ToolStripPanelThis 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.

DockedThe 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 PositionedThis 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

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

ShortcutsShortcuts 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

NavigationAlt 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

Page 6: ToolStrip GTM

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

SampleRun the following sample; it shows the font flows into the veggies menu dropdown, but not fruit.// explicitContextMenuStrip 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");

// menustripMenuStrip ms = new MenuStrip();// set Font to show property flowms.Font = new Font("Tebuchet MS", 14, FontStyle.Bold);ms.Items.Add(fruitMenuItem);

Page 7: ToolStrip GTM

ms.Items.Add(veggiesMenuItem);this.Controls.Add(ms);

1.8 Image scalingImage scaling is determined by the interaction of several properties.

size ToolStrip.ImageScalingSizeThis 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.ImageScalingThis 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 AutoSize

ToolStripItem.ImageScalingModeSizeToFit None

TRUE Scales to ToolStrip.ImageScalingSize

No Image ScalingToolStrip sizes to largest of largest item or minimum size

FALSE Scales to area remaining in ToolStrip

No Image ScalingNo 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 CustomizationThe two avenues of customization covered here are custom ToolStripItems at design time and custom renderer custom ToolStrips at design time.

Custom ToolStripItemsCustom 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: ToolStripItemDesignerAvailabilityThis 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 preservedpublic 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

Page 8: ToolStrip GTM

[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 ToolStripsCustom 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 @ DesignTimepublic 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

Page 9: ToolStrip GTM

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 CommandingBy 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

Page 10: ToolStrip GTM

2 ToolStripThis 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 ItemsToolStripButton - defaultToolStripSeparatorToolStripLabelToolStripDropDownButtonToolStripSplitButtonToolStripTextBoxToolStripComboBox

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 LayoutBy 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

StackWithOverflowDefault for ToolStrip, this ToolStripLayoutStyle automatically alters it’s layout based on the orientation property of the ToolStrip to handle drag to dock scenarios.

VerticalStackWithOverflowJust like StackWithOverflow except always renders as vertical.

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

Page 11: ToolStrip GTM

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.

.

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

Page 12: ToolStrip GTM

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

DockToolStrips 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 ToolStripItemToolStripItem 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

Page 13: ToolStrip GTM

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.

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

DisplayStyleDisplayStyle 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 VisibleIn 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 CloningBy 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;

Page 14: ToolStrip GTM

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 ToolStripLabelToolStripLabel 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 ToolStripButtonToolStripButton is the button item for ToolStrips. It is very similar to ToolStripLabel but also supports depressed rendering, borders, focus, and other key interactions.

Page 15: ToolStrip GTM

How do I get toggle button?toolStripButton.CheckOnClick = true;toolStripButton.CheckedChanged += new EventHandler(toolStripButton_CheckedChanged);

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

Page 16: ToolStrip GTM

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 ToolStripControlHostThe 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 thist.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;

Page 17: ToolStrip GTM

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

Page 18: ToolStrip GTM

2.8 ToolStripTextBoxToolStripText 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 ToolStripComboBoxToolStripCombo 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 ToolStripDropDownItemToolStripDropDownItem 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, DropDownItemYou 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 CollectionToolStripMenuItem veggiesMenuItem = new ToolStripMenuItem("Veggies");veggiesMenuItem.DropDownItems.Add("Asparagus");veggiesMenuItem.DropDownItems.Add("Bok Choy");veggiesMenuItem.DropDownItems.Add("Cauliflower");// Hook up the handlerveggiesMenuItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(myDropDownItemClicked);

// assign a dropdownContextMenuStrip 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 handlerfruitMenuItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(myDropDownItemClicked);

// menustripMenuStrip ms = new MenuStrip();

Page 19: ToolStrip GTM

ms.Items.Add(fruitMenuItem);ms.Items.Add(veggiesMenuItem);this.Controls.Add(ms);

2.11 ToolStripDropDownButtonThis 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 ToolStripDropDownButtonVery 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 ToolStripSplitButtonThis 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.

DefaultItemToolStripSplitButton.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);// menustripToolStrip 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 ToolTipsToolTips are intrinsically supported within ToolStrips. Below lists relevant properties and their affect on ToolTips.

ToolStrip.ShowItemToolTipsThis is to enable ToolTips for the entire ToolStrip. Default is true for ToolStrip, ContextMenuStrip, false for MenuStrip, StatusStrip.

toolStrip.ShowItemToolTips = true

Text

Page 20: ToolStrip GTM

By default ToolStripItems use the Text property as the textual source for the tooltip content. To alter this, set AutoToolTip to false.

AutoTooltipAutoToolTip 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 AlignmentAlignment 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 OverflowTo 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 sampleThe 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;

Page 21: ToolStrip GTM

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

Page 22: ToolStrip GTM

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

Page 23: ToolStrip GTM

3 MenuStripMenuStrip 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 ItemsToolStripMenuItem - defaultToolStripTextBoxToolStripComboBox

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 ToolStripMenuItemToolStripMenuItem 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 StretchWhen 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 MDIThe 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.MDIWindowListItemThis property identifies the item whose drop down should be populated with the titles of MDI children associated with this MDI Parent.

ToolStripMenuItem.IsMdiWindowListEntryThis 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 mergingMerging 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.

Page 24: ToolStrip GTM

NOTE: See the manual merging sections in ToolStripManager section 6.1.

Procedure for automatically merging an MDI child menu into a MDI parentThe 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 = menuStrip13. Create an MDI child form, setting MdiChildForm.MdiParent = MainForm4. Add a MenuStrip to the MDI child5. Set the MenuStrip in the MdiChildForm to Visible = false6. 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).

Page 25: ToolStrip GTM

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.

Page 26: ToolStrip GTM

4 StatusStripStatusStrip 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 LayoutOne 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 ItemsToolStripStatusLabel - defaultToolStripDropDownButtonToolStripSplitButtonToolStripProgressBar

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 ToolStripStatusLabelToolStripStatusLabel is a special version of ToolStripLabel designed specifically for use in StatusStrip. The special features include BorderStyle, BorderSides and Spring.

4.3 ToolStripProgressBarToolStripCombo 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 & GripThere are two different grips on StatusStrip.

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

SizingGripSizingGrip 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

Page 27: ToolStrip GTM

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

Page 28: ToolStrip GTM

5 ContextMenuStripContextMenuStrip 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 ItemsToolStripMenuItem - defaultToolStripSeparatorToolStripTextBoxToolStripComboBox

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 SampleContextMenuStrip.Openinge.Cancel handling with no itemsDynamic SourceControl determination w/ reuseDynamic 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;

Page 29: ToolStrip GTM

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

Page 30: ToolStrip GTM

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

Page 31: ToolStrip GTM

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 Marginsenable/disable check marginenable/disable image margincheck 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;

Page 32: ToolStrip GTM

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

}

Page 33: ToolStrip GTM

}

5.6 DropDownDirectionDropDownDirection 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 dropdownThis is a rather spiffy article: http://blogs.msdn.com/jfoscoding/archive/2005/03/03/384430.aspx

Page 34: ToolStrip GTM

6 ToolStripManagerToolStripManager is a static class that handles application wide ToolStrip related tasks such as merging, settings and renderer exposure.

6.1 MergingToolStripMerging 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

ManualManual 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 menustripMenuStrip veggieMenuStrip = new MenuStrip();ToolStripMenuItem veggieMenuStripItem = veggieMenuStrip.Items.Add("Veggies") as ToolStripMenuItem;veggieMenuStripItem.DropDownItems.Add("Asparagus");veggieMenuStripItem.DropDownItems.Add("Jicama");veggieMenuStripItem.DropDownItems.Add("Kale");

// source menustripMenuStrip veggieMenuStrip2 = new MenuStrip();ToolStripMenuItem veggieMenuStripItem2 = veggieMenuStrip2.Items.Add("Veggies") as ToolStripMenuItem;veggieMenuStripItem2.DropDownItems.Add("Cauliflower");veggieMenuStripItem2.DropDownItems.Add("Bok Choy");

Page 35: ToolStrip GTM

// set top level item to MatchOnlyveggieMenuStripItem2.MergeAction = MergeAction.MatchOnly;

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

// do this on activation or focusToolStripManager.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 SettingsSettings 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 savedToolStripManager.LoadSettings(this);}

private void Form1_FormClosing(object sender, FormClosingEventArgs e){// Save out current state of ToolStripsToolStripManager.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 componentToolStripManager.SaveSettings(this, "RESET");

// load and apply settings last savedToolStripManager.LoadSettings(this);}

private void newToolStripMenuItem_Click(object sender, EventArgs e){// apply the RESET settings

Page 36: ToolStrip GTM

ToolStripManager.LoadSettings(this, "RESET");}

private void Form1_FormClosing(object sender, FormClosingEventArgs e){// Save out current state of ToolStripsToolStripManager.SaveSettings(this);}

Page 37: ToolStrip GTM

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)

SampleForm 6

Custom RendererSetting Renderer per toolstripSetting 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");

Page 38: ToolStrip GTM

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

Page 39: ToolStrip GTM

} }

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 ToolStripProfessionalColorTable 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 OldProfessionalRendererPass in a new ProfessionalColorTable with professionalColorTable.UseSystemColors = false;In the OldProfessionalRenderer class, override the following methods:

OnRenderImageMargin (clear with ControlLight), OnRenderBorder (do nothing),

Page 40: ToolStrip GTM

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

}}

Page 41: ToolStrip GTM

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

Page 42: ToolStrip GTM

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 Sample2Below 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

Page 43: ToolStrip GTM

{ 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 ConnectedAreaConnected 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 selectionBelow 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;

Page 44: ToolStrip GTM

9 ToolStripSystemRendererThe System Renderer renders ToolStrips similar to Win32 look and feel. You can use with or without VisualStyles by

ToolStripManager.VisualStylesEnabled = false;

Page 45: ToolStrip GTM

10 ToolStripContainerToolStrip 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 – ToolStripPanelsThe 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 panelstoolStripContainer1.LeftToolStripPanelVisible = false;toolStripContainer1.RightToolStripPanelVisible = false;

Center – ContentPanelThe 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 TimeToolStripContainer offers several design time features not found on other controls. Below is a description of a few of these.

Expando handlesOn 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 ControlsA 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 SupportToolStripContainer 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.

Page 46: ToolStrip GTM

11 ToolStripPanelToolStripPanel 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 SupportThe 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;

Page 47: ToolStrip GTM

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.