Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / WinForms / Managed / System / WinForms / ToolStripSplitButton.cs / 1 / ToolStripSplitButton.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Windows.Forms {
using System;
using System.Security;
using System.Security.Permissions;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.ComponentModel;
using System.Windows.Forms.Design;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Diagnostics;
using System.Windows.Forms.Layout;
///
///
[
ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip),
DefaultEvent("ButtonClick")
]
public class ToolStripSplitButton : ToolStripDropDownItem {
private ToolStripItem defaultItem = null;
private ToolStripSplitButtonButton splitButtonButton = null;
private Rectangle dropDownButtonBounds = Rectangle.Empty;
private ToolStripSplitButtonButtonLayout splitButtonButtonLayout = null;
private int dropDownButtonWidth = 0;
private int splitterWidth = 1;
private Rectangle splitterBounds = Rectangle.Empty;
private byte openMouseId = 0;
private long lastClickTime = 0;
private const int DEFAULT_DROPDOWN_WIDTH = 11;
private static readonly object EventDefaultItemChanged = new object();
private static readonly object EventButtonClick = new object();
private static readonly object EventButtonDoubleClick = new object();
private static readonly object EventDropDownOpened = new object();
private static readonly object EventDropDownClosed = new object();
///
///
/// Summary of ToolStripSplitButton.
///
public ToolStripSplitButton() {
Initialize(); // all additional work should be done in Initialize
}
public ToolStripSplitButton(string text):base(text,null,(EventHandler)null) {
Initialize();
}
public ToolStripSplitButton(Image image):base(null,image,(EventHandler)null) {
Initialize();
}
public ToolStripSplitButton(string text, Image image):base(text,image,(EventHandler)null) {
Initialize();
}
public ToolStripSplitButton(string text, Image image, EventHandler onClick):base(text,image,onClick) {
Initialize();
}
public ToolStripSplitButton(string text, Image image, EventHandler onClick, string name) :base(text,image,onClick,name){
Initialize();
}
public ToolStripSplitButton(string text, Image image, params ToolStripItem[] dropDownItems):base(text,image,dropDownItems) {
Initialize();
}
[DefaultValue(true)]
public new bool AutoToolTip {
get {
return base.AutoToolTip;
}
set {
base.AutoToolTip = value;
}
}
///
///
/// Summary of ToolStripSplitButton.
///
[Browsable(false)]
public Rectangle ButtonBounds {
get {
//Rectangle bounds = SplitButtonButton.Bounds;
//bounds.Offset(this.Bounds.Location);
return SplitButtonButton.Bounds;
}
}
///
///
/// Summary of ButtonPressed.
///
[Browsable(false)]
public bool ButtonPressed {
get {
return SplitButtonButton.Pressed;
}
}
///
///
/// Summary of ButtonPressed.
///
[Browsable(false)]
public bool ButtonSelected {
get {
return SplitButtonButton.Selected || DropDownButtonPressed;
}
}
///
///
/// Occurs when the button portion of a split button is clicked.
///
[
SRCategory(SR.CatAction),
SRDescription(SR.ToolStripSplitButtonOnButtonClickDescr)
]
public event EventHandler ButtonClick {
add {
Events.AddHandler(EventButtonClick, value);
}
remove {
Events.RemoveHandler(EventButtonClick, value);
}
}
///
///
/// Occurs when the utton portion of a split button is double clicked.
///
[
SRCategory(SR.CatAction),
SRDescription(SR.ToolStripSplitButtonOnButtonDoubleClickDescr)
]
public event EventHandler ButtonDoubleClick {
add {
Events.AddHandler(EventButtonDoubleClick, value);
}
remove {
Events.RemoveHandler(EventButtonDoubleClick, value);
}
}
protected override bool DefaultAutoToolTip {
get {
return true;
}
}
///
///
/// Summary of DefaultItem.
///
[DefaultValue(null), Browsable(false)]
public ToolStripItem DefaultItem {
get {
return defaultItem;
}
set {
if (defaultItem != value) {
OnDefaultItemChanged(new EventArgs());
defaultItem = value;
}
}
}
///
///
/// Occurs when the default item has changed
///
[
SRCategory(SR.CatAction),
SRDescription(SR.ToolStripSplitButtonOnDefaultItemChangedDescr)
]
public event EventHandler DefaultItemChanged {
add {
Events.AddHandler(EventDefaultItemChanged, value);
}
remove {
Events.RemoveHandler(EventDefaultItemChanged, value);
}
}
///
///
/// specifies the default behavior of these items on ToolStripDropDowns when clicked.
///
internal protected override bool DismissWhenClicked {
get {
return DropDown.Visible != true;
}
}
internal override Rectangle DropDownButtonArea {
get { return this.DropDownButtonBounds; }
}
///
///
/// The bounds of the DropDown in ToolStrip coordinates.
///
[Browsable(false)]
public Rectangle DropDownButtonBounds {
get {
return dropDownButtonBounds;
}
}
///
///
/// Summary of DropDownButtonBounds.
///
[Browsable(false)]
public bool DropDownButtonPressed {
get {
//
return DropDown.Visible;
}
}
///
///
/// Summary of DropDownButtonSelected.
///
[Browsable(false)]
public bool DropDownButtonSelected{
get {
return this.Selected;
}
}
///
///
/// Summary of DropDownButtonWidth.
///
[
SRCategory(SR.CatLayout),
SRDescription(SR.ToolStripSplitButtonDropDownButtonWidthDescr)
]
public int DropDownButtonWidth {
get{
return dropDownButtonWidth;
}
set {
if (value < 0) {
// throw if less than 0.
throw new ArgumentOutOfRangeException("DropDownButtonWidth", SR.GetString(SR.InvalidLowBoundArgumentEx, "DropDownButtonWidth", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture)));
}
if (dropDownButtonWidth != value) {
dropDownButtonWidth = value;
InvalidateSplitButtonLayout();
InvalidateItemLayout(PropertyNames.DropDownButtonWidth, true);
}
}
}
///
/// This is here for serialization purposes.
///
private int DefaultDropDownButtonWidth {
get {
// lets start off with a size roughly equivilant to a combobox dropdown
return DEFAULT_DROPDOWN_WIDTH;
}
}
///
/// Just used as a convenience to help manage layout
///
private ToolStripSplitButtonButton SplitButtonButton {
get {
if (splitButtonButton == null) {
splitButtonButton = new ToolStripSplitButtonButton(this);
}
splitButtonButton.Image = this.Image;
splitButtonButton.Text = this.Text;
splitButtonButton.BackColor = this.BackColor;
splitButtonButton.ForeColor = this.ForeColor;
splitButtonButton.Font = this.Font;
splitButtonButton.ImageAlign = this.ImageAlign;
splitButtonButton.TextAlign = this.TextAlign;
splitButtonButton.TextImageRelation = this.TextImageRelation;
return splitButtonButton;
}
}
///
/// Summary of SplitButtonButtonLayout.
///
internal ToolStripItemInternalLayout SplitButtonButtonLayout {
get {
// For preferred size caching reasons, we need to keep our two
// internal layouts (button, dropdown button) in [....].
if (InternalLayout != null /*if layout is invalid - calls CreateInternalLayout - which resets splitButtonButtonLayout to null*/
&& splitButtonButtonLayout == null) {
splitButtonButtonLayout = new ToolStripSplitButtonButtonLayout(this);
}
return splitButtonButtonLayout;
}
}
///
///
/// the width of the separator between the default and drop down button
///
[
SRDescription(SR.ToolStripSplitButtonSplitterWidthDescr),
SRCategory(SR.CatLayout),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Advanced)
]
internal int SplitterWidth {
get {
return splitterWidth;
}
set {
if (value < 0) {
splitterWidth = 0;
}
else {
splitterWidth = value;
}
InvalidateSplitButtonLayout();
}
}
///
///
/// the boundaries of the separator between the default and drop down button, exposed for custom
/// painting purposes.
///
[Browsable(false)]
public Rectangle SplitterBounds {
get {
return splitterBounds;
}
}
///
/// Summary of CalculateLayout.
///
private void CalculateLayout() {
// Figure out where the DropDown image goes.
Rectangle dropDownButtonBounds = new Rectangle(Point.Empty, this.Size);
Rectangle splitButtonButtonBounds = Rectangle.Empty;
dropDownButtonBounds = new Rectangle(Point.Empty, new Size(Math.Min(this.Width, DropDownButtonWidth), this.Height));
// Figure out the height and width of the selected item.
int splitButtonButtonWidth = Math.Max(0, this.Width - dropDownButtonBounds.Width);
int splitButtonButtonHeight = Math.Max(0, this.Height);
splitButtonButtonBounds = new Rectangle(Point.Empty, new Size(splitButtonButtonWidth, splitButtonButtonHeight));
// grow the selected item by one since we're overlapping the borders.
splitButtonButtonBounds.Width -= splitterWidth;
if (this.RightToLeft == RightToLeft.No) {
// the dropdown button goes on the right
dropDownButtonBounds.Offset(splitButtonButtonBounds.Right+splitterWidth, 0);
splitterBounds = new Rectangle(splitButtonButtonBounds.Right, splitButtonButtonBounds.Top, splitterWidth, splitButtonButtonBounds.Height);
}
else {
// the split button goes on the right.
splitButtonButtonBounds.Offset(DropDownButtonWidth+splitterWidth, 0);
splitterBounds = new Rectangle(dropDownButtonBounds.Right, dropDownButtonBounds.Top, splitterWidth, dropDownButtonBounds.Height);
}
this.SplitButtonButton.SetBounds(splitButtonButtonBounds);
this.SetDropDownButtonBounds(dropDownButtonBounds);
}
protected override AccessibleObject CreateAccessibilityInstance() {
return new ToolStripSplitButtonAccessibleObject(this);
}
protected override ToolStripDropDown CreateDefaultDropDown() {
// AutoGenerate a Winbar DropDown - set the property so we hook events
return new ToolStripDropDownMenu(this, /*isAutoGenerated=*/true);
}
internal override ToolStripItemInternalLayout CreateInternalLayout() {
// whenever the master layout is invalidated - invalidate the splitbuttonbutton layout.
this.splitButtonButtonLayout = null;
return new ToolStripItemInternalLayout(this);
}
///
public override Size GetPreferredSize(Size constrainingSize) {
Size preferredSize = SplitButtonButtonLayout.GetPreferredSize(constrainingSize);
preferredSize.Width += DropDownButtonWidth + SplitterWidth + Padding.Horizontal;
return preferredSize;
}
///
/// Summary of InvalidateSplitButtonLayout.
///
private void InvalidateSplitButtonLayout() {
this.splitButtonButtonLayout = null;
CalculateLayout();
}
private void Initialize() {
dropDownButtonWidth = DefaultDropDownButtonWidth;
SupportsSpaceKey = true;
}
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected internal override bool ProcessDialogKey(Keys keyData) {
if (Enabled && (keyData == Keys.Enter || (SupportsSpaceKey && keyData == Keys.Space))) {
PerformButtonClick();
return true;
}
return base.ProcessDialogKey(keyData);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")] // 'charCode' matches control.cs
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected internal override bool ProcessMnemonic(char charCode) {
// checking IsMnemonic is not necessary - toolstrip does this for us
PerformButtonClick();
return true;
}
///
///
/// called when the button portion of a split button is clicked
/// if there is a default item, this will route the click to the default item
///
protected virtual void OnButtonClick(System.EventArgs e) {
if (DefaultItem != null) {
DefaultItem.FireEvent(ToolStripItemEventType.Click);
}
EventHandler handler = (EventHandler)Events[EventButtonClick];
if (handler != null) handler(this, e);
}
///
///
/// called when the button portion of a split button is double clicked
/// if there is a default item, this will route the double click to the default item
///
public virtual void OnButtonDoubleClick(System.EventArgs e) {
if (DefaultItem != null) {
DefaultItem.FireEvent(ToolStripItemEventType.DoubleClick);
}
EventHandler handler = (EventHandler)Events[EventButtonDoubleClick];
if (handler != null) handler(this,e);
}
///
///
/// Inheriting classes should override this method to handle this event.
///
protected virtual void OnDefaultItemChanged(EventArgs e) {
InvalidateSplitButtonLayout();
if (CanRaiseEvents) {
EventHandler eh = Events[EventDefaultItemChanged] as EventHandler;
if (eh != null) {
eh(this, e);
}
}
}
///
///
/// Summary of OnMouseDown.
///
protected override void OnMouseDown(MouseEventArgs e) {
if (DropDownButtonBounds.Contains(e.Location)) {
if (e.Button == MouseButtons.Left) {
if (!DropDown.Visible) {
Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID");
openMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId();
this.ShowDropDown(/*mousePress = */true);
}
}
}
else {
SplitButtonButton.Push(true);
}
}
///
///
/// Summary of OnMouseUp.
///
protected override void OnMouseUp(MouseEventArgs e) {
if (!Enabled) {
return;
}
SplitButtonButton.Push(false);
if (DropDownButtonBounds.Contains(e.Location)) {
if (e.Button == MouseButtons.Left) {
if (DropDown.Visible) {
Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID");
byte closeMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId();
if (closeMouseId != openMouseId) {
openMouseId = 0; // reset the mouse id, we should never get this value from toolstrip.
ToolStripManager.ModalMenuFilter.CloseActiveDropDown(DropDown, ToolStripDropDownCloseReason.AppClicked);
Select();
}
}
}
}
Point clickPoint = new Point(e.X, e.Y);
if ((e.Button == MouseButtons.Left) && this.SplitButtonButton.Bounds.Contains(clickPoint)) {
bool shouldFireDoubleClick = false;
if (DoubleClickEnabled) {
long newTime = DateTime.Now.Ticks;
long deltaTicks = newTime - lastClickTime;
lastClickTime = newTime;
// use >= for cases where the succession of click events is so fast it's not picked up by
// DateTime resolution.
Debug.Assert(deltaTicks >= 0, "why are deltaticks less than zero? thats some mighty fast clicking");
// if we've seen a mouse up less than the double click time ago, we should fire.
if (deltaTicks >= 0 && deltaTicks < DoubleClickTicks) {
shouldFireDoubleClick = true;
}
}
if (shouldFireDoubleClick) {
OnButtonDoubleClick(new System.EventArgs());
// VSWhidbey 486983: if we actually fired DoubleClick - reset the lastClickTime.
lastClickTime = 0;
}
else {
OnButtonClick(new System.EventArgs());
}
}
}
///
protected override void OnMouseLeave(EventArgs e) {
openMouseId = 0; // reset the mouse id, we should never get this value from toolstrip.
SplitButtonButton.Push(false);
base.OnMouseLeave(e);
}
///
///
/// Summary of OnRightToLeftChanged.
///
protected override void OnRightToLeftChanged(EventArgs e) {
base.OnRightToLeftChanged(e);
InvalidateSplitButtonLayout();
}
///
///
/// Summary of OnPaint.
///
///
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
ToolStripRenderer renderer = this.Renderer;
if (renderer != null) {
InvalidateSplitButtonLayout();
Graphics g = e.Graphics;
renderer.DrawSplitButton(new ToolStripItemRenderEventArgs(g, this));
if ((DisplayStyle & ToolStripItemDisplayStyle.Image) != ToolStripItemDisplayStyle.None) {
renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, SplitButtonButtonLayout.ImageRectangle));
}
if ((DisplayStyle & ToolStripItemDisplayStyle.Text) != ToolStripItemDisplayStyle.None) {
renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, SplitButtonButton.Text, SplitButtonButtonLayout.TextRectangle, this.ForeColor, this.Font, SplitButtonButtonLayout.TextFormat));
}
}
}
public void PerformButtonClick() {
if (Enabled && Available) {
PerformClick();
OnButtonClick(EventArgs.Empty);
}
}
///
///
/// Resets the RightToLeft to be the default.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual void ResetDropDownButtonWidth() {
DropDownButtonWidth = DefaultDropDownButtonWidth;
}
///
/// Summary of SetDropDownBounds.
///
private void SetDropDownButtonBounds(Rectangle rect) {
dropDownButtonBounds = rect;
}
///
/// Determines if the property needs to be persisted.
///
[EditorBrowsable(EditorBrowsableState.Never)]
internal virtual bool ShouldSerializeDropDownButtonWidth() {
return (DropDownButtonWidth != DefaultDropDownButtonWidth);
}
///
/// This class represents the item to the left of the dropdown [ A |v] (e.g the "A")
/// It exists so that we can use our existing methods for text and image layout
/// and have a place to stick certain state information like pushed and selected
/// Note since this is NOT an actual item hosted on the Winbar - it wont get things
/// like MouseOver, wont be laid out by the ToolStrip, etc etc. This is purely internal
/// convenience.
///
private class ToolStripSplitButtonButton : ToolStripButton {
private ToolStripSplitButton owner = null;
public ToolStripSplitButtonButton(ToolStripSplitButton owner) {
this.owner = owner;
}
public override bool Enabled {
get {
return owner.Enabled;
}
set {
// do nothing
}
}
public override ToolStripItemDisplayStyle DisplayStyle {
get {
return owner.DisplayStyle;
}
set {
// do nothing
}
}
public override Padding Padding {
get {
return this.owner.Padding;
}
set {
// do nothing
}
}
public override ToolStripTextDirection TextDirection {
get {
return owner.TextDirection;
}
}
public override Image Image {
get {
if ((owner.DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image) {
return owner.Image;
}
else {
return null;
}
}
set {
// do nothing
}
}
public override bool Selected {
get {
if (owner != null) {
return owner.Selected;
}
return base.Selected;
}
}
public override string Text {
get {
if ((owner.DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) {
return owner.Text;
}
else {
return null;
}
}
set {
// do nothing
}
}
}
///
/// This class performs internal layout for the "split button button" portion of a split button.
/// Its main job is to make sure the inner button has the same parent as the split button, so
/// that layout can be performed using the correct graphics context.
///
private class ToolStripSplitButtonButtonLayout : ToolStripItemInternalLayout {
ToolStripSplitButton owner;
public ToolStripSplitButtonButtonLayout(ToolStripSplitButton owner) : base(owner.SplitButtonButton) {
this.owner = owner;
}
protected override ToolStripItem Owner {
get { return owner; }
}
protected override ToolStrip ParentInternal {
get {
return owner.ParentInternal;
}
}
public override Rectangle ImageRectangle {
get {
Rectangle imageRect = base.ImageRectangle;
// translate to ToolStripItem coordinates
imageRect.Offset(owner.SplitButtonButton.Bounds.Location);
return imageRect;
}
}
public override Rectangle TextRectangle {
get {
Rectangle textRect = base.TextRectangle;
// translate to ToolStripItem coordinates
textRect.Offset(owner.SplitButtonButton.Bounds.Location);
return textRect;
}
}
}
///
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class ToolStripSplitButtonAccessibleObject : ToolStripItem.ToolStripItemAccessibleObject {
private ToolStripSplitButton owner;
public ToolStripSplitButtonAccessibleObject(ToolStripSplitButton item) : base(item) {
owner = item;
}
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public override void DoDefaultAction() {
owner.PerformButtonClick();
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Windows.Forms {
using System;
using System.Security;
using System.Security.Permissions;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.ComponentModel;
using System.Windows.Forms.Design;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Diagnostics;
using System.Windows.Forms.Layout;
///
///
[
ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip),
DefaultEvent("ButtonClick")
]
public class ToolStripSplitButton : ToolStripDropDownItem {
private ToolStripItem defaultItem = null;
private ToolStripSplitButtonButton splitButtonButton = null;
private Rectangle dropDownButtonBounds = Rectangle.Empty;
private ToolStripSplitButtonButtonLayout splitButtonButtonLayout = null;
private int dropDownButtonWidth = 0;
private int splitterWidth = 1;
private Rectangle splitterBounds = Rectangle.Empty;
private byte openMouseId = 0;
private long lastClickTime = 0;
private const int DEFAULT_DROPDOWN_WIDTH = 11;
private static readonly object EventDefaultItemChanged = new object();
private static readonly object EventButtonClick = new object();
private static readonly object EventButtonDoubleClick = new object();
private static readonly object EventDropDownOpened = new object();
private static readonly object EventDropDownClosed = new object();
///
///
/// Summary of ToolStripSplitButton.
///
public ToolStripSplitButton() {
Initialize(); // all additional work should be done in Initialize
}
public ToolStripSplitButton(string text):base(text,null,(EventHandler)null) {
Initialize();
}
public ToolStripSplitButton(Image image):base(null,image,(EventHandler)null) {
Initialize();
}
public ToolStripSplitButton(string text, Image image):base(text,image,(EventHandler)null) {
Initialize();
}
public ToolStripSplitButton(string text, Image image, EventHandler onClick):base(text,image,onClick) {
Initialize();
}
public ToolStripSplitButton(string text, Image image, EventHandler onClick, string name) :base(text,image,onClick,name){
Initialize();
}
public ToolStripSplitButton(string text, Image image, params ToolStripItem[] dropDownItems):base(text,image,dropDownItems) {
Initialize();
}
[DefaultValue(true)]
public new bool AutoToolTip {
get {
return base.AutoToolTip;
}
set {
base.AutoToolTip = value;
}
}
///
///
/// Summary of ToolStripSplitButton.
///
[Browsable(false)]
public Rectangle ButtonBounds {
get {
//Rectangle bounds = SplitButtonButton.Bounds;
//bounds.Offset(this.Bounds.Location);
return SplitButtonButton.Bounds;
}
}
///
///
/// Summary of ButtonPressed.
///
[Browsable(false)]
public bool ButtonPressed {
get {
return SplitButtonButton.Pressed;
}
}
///
///
/// Summary of ButtonPressed.
///
[Browsable(false)]
public bool ButtonSelected {
get {
return SplitButtonButton.Selected || DropDownButtonPressed;
}
}
///
///
/// Occurs when the button portion of a split button is clicked.
///
[
SRCategory(SR.CatAction),
SRDescription(SR.ToolStripSplitButtonOnButtonClickDescr)
]
public event EventHandler ButtonClick {
add {
Events.AddHandler(EventButtonClick, value);
}
remove {
Events.RemoveHandler(EventButtonClick, value);
}
}
///
///
/// Occurs when the utton portion of a split button is double clicked.
///
[
SRCategory(SR.CatAction),
SRDescription(SR.ToolStripSplitButtonOnButtonDoubleClickDescr)
]
public event EventHandler ButtonDoubleClick {
add {
Events.AddHandler(EventButtonDoubleClick, value);
}
remove {
Events.RemoveHandler(EventButtonDoubleClick, value);
}
}
protected override bool DefaultAutoToolTip {
get {
return true;
}
}
///
///
/// Summary of DefaultItem.
///
[DefaultValue(null), Browsable(false)]
public ToolStripItem DefaultItem {
get {
return defaultItem;
}
set {
if (defaultItem != value) {
OnDefaultItemChanged(new EventArgs());
defaultItem = value;
}
}
}
///
///
/// Occurs when the default item has changed
///
[
SRCategory(SR.CatAction),
SRDescription(SR.ToolStripSplitButtonOnDefaultItemChangedDescr)
]
public event EventHandler DefaultItemChanged {
add {
Events.AddHandler(EventDefaultItemChanged, value);
}
remove {
Events.RemoveHandler(EventDefaultItemChanged, value);
}
}
///
///
/// specifies the default behavior of these items on ToolStripDropDowns when clicked.
///
internal protected override bool DismissWhenClicked {
get {
return DropDown.Visible != true;
}
}
internal override Rectangle DropDownButtonArea {
get { return this.DropDownButtonBounds; }
}
///
///
/// The bounds of the DropDown in ToolStrip coordinates.
///
[Browsable(false)]
public Rectangle DropDownButtonBounds {
get {
return dropDownButtonBounds;
}
}
///
///
/// Summary of DropDownButtonBounds.
///
[Browsable(false)]
public bool DropDownButtonPressed {
get {
//
return DropDown.Visible;
}
}
///
///
/// Summary of DropDownButtonSelected.
///
[Browsable(false)]
public bool DropDownButtonSelected{
get {
return this.Selected;
}
}
///
///
/// Summary of DropDownButtonWidth.
///
[
SRCategory(SR.CatLayout),
SRDescription(SR.ToolStripSplitButtonDropDownButtonWidthDescr)
]
public int DropDownButtonWidth {
get{
return dropDownButtonWidth;
}
set {
if (value < 0) {
// throw if less than 0.
throw new ArgumentOutOfRangeException("DropDownButtonWidth", SR.GetString(SR.InvalidLowBoundArgumentEx, "DropDownButtonWidth", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture)));
}
if (dropDownButtonWidth != value) {
dropDownButtonWidth = value;
InvalidateSplitButtonLayout();
InvalidateItemLayout(PropertyNames.DropDownButtonWidth, true);
}
}
}
///
/// This is here for serialization purposes.
///
private int DefaultDropDownButtonWidth {
get {
// lets start off with a size roughly equivilant to a combobox dropdown
return DEFAULT_DROPDOWN_WIDTH;
}
}
///
/// Just used as a convenience to help manage layout
///
private ToolStripSplitButtonButton SplitButtonButton {
get {
if (splitButtonButton == null) {
splitButtonButton = new ToolStripSplitButtonButton(this);
}
splitButtonButton.Image = this.Image;
splitButtonButton.Text = this.Text;
splitButtonButton.BackColor = this.BackColor;
splitButtonButton.ForeColor = this.ForeColor;
splitButtonButton.Font = this.Font;
splitButtonButton.ImageAlign = this.ImageAlign;
splitButtonButton.TextAlign = this.TextAlign;
splitButtonButton.TextImageRelation = this.TextImageRelation;
return splitButtonButton;
}
}
///
/// Summary of SplitButtonButtonLayout.
///
internal ToolStripItemInternalLayout SplitButtonButtonLayout {
get {
// For preferred size caching reasons, we need to keep our two
// internal layouts (button, dropdown button) in [....].
if (InternalLayout != null /*if layout is invalid - calls CreateInternalLayout - which resets splitButtonButtonLayout to null*/
&& splitButtonButtonLayout == null) {
splitButtonButtonLayout = new ToolStripSplitButtonButtonLayout(this);
}
return splitButtonButtonLayout;
}
}
///
///
/// the width of the separator between the default and drop down button
///
[
SRDescription(SR.ToolStripSplitButtonSplitterWidthDescr),
SRCategory(SR.CatLayout),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Advanced)
]
internal int SplitterWidth {
get {
return splitterWidth;
}
set {
if (value < 0) {
splitterWidth = 0;
}
else {
splitterWidth = value;
}
InvalidateSplitButtonLayout();
}
}
///
///
/// the boundaries of the separator between the default and drop down button, exposed for custom
/// painting purposes.
///
[Browsable(false)]
public Rectangle SplitterBounds {
get {
return splitterBounds;
}
}
///
/// Summary of CalculateLayout.
///
private void CalculateLayout() {
// Figure out where the DropDown image goes.
Rectangle dropDownButtonBounds = new Rectangle(Point.Empty, this.Size);
Rectangle splitButtonButtonBounds = Rectangle.Empty;
dropDownButtonBounds = new Rectangle(Point.Empty, new Size(Math.Min(this.Width, DropDownButtonWidth), this.Height));
// Figure out the height and width of the selected item.
int splitButtonButtonWidth = Math.Max(0, this.Width - dropDownButtonBounds.Width);
int splitButtonButtonHeight = Math.Max(0, this.Height);
splitButtonButtonBounds = new Rectangle(Point.Empty, new Size(splitButtonButtonWidth, splitButtonButtonHeight));
// grow the selected item by one since we're overlapping the borders.
splitButtonButtonBounds.Width -= splitterWidth;
if (this.RightToLeft == RightToLeft.No) {
// the dropdown button goes on the right
dropDownButtonBounds.Offset(splitButtonButtonBounds.Right+splitterWidth, 0);
splitterBounds = new Rectangle(splitButtonButtonBounds.Right, splitButtonButtonBounds.Top, splitterWidth, splitButtonButtonBounds.Height);
}
else {
// the split button goes on the right.
splitButtonButtonBounds.Offset(DropDownButtonWidth+splitterWidth, 0);
splitterBounds = new Rectangle(dropDownButtonBounds.Right, dropDownButtonBounds.Top, splitterWidth, dropDownButtonBounds.Height);
}
this.SplitButtonButton.SetBounds(splitButtonButtonBounds);
this.SetDropDownButtonBounds(dropDownButtonBounds);
}
protected override AccessibleObject CreateAccessibilityInstance() {
return new ToolStripSplitButtonAccessibleObject(this);
}
protected override ToolStripDropDown CreateDefaultDropDown() {
// AutoGenerate a Winbar DropDown - set the property so we hook events
return new ToolStripDropDownMenu(this, /*isAutoGenerated=*/true);
}
internal override ToolStripItemInternalLayout CreateInternalLayout() {
// whenever the master layout is invalidated - invalidate the splitbuttonbutton layout.
this.splitButtonButtonLayout = null;
return new ToolStripItemInternalLayout(this);
}
///
public override Size GetPreferredSize(Size constrainingSize) {
Size preferredSize = SplitButtonButtonLayout.GetPreferredSize(constrainingSize);
preferredSize.Width += DropDownButtonWidth + SplitterWidth + Padding.Horizontal;
return preferredSize;
}
///
/// Summary of InvalidateSplitButtonLayout.
///
private void InvalidateSplitButtonLayout() {
this.splitButtonButtonLayout = null;
CalculateLayout();
}
private void Initialize() {
dropDownButtonWidth = DefaultDropDownButtonWidth;
SupportsSpaceKey = true;
}
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected internal override bool ProcessDialogKey(Keys keyData) {
if (Enabled && (keyData == Keys.Enter || (SupportsSpaceKey && keyData == Keys.Space))) {
PerformButtonClick();
return true;
}
return base.ProcessDialogKey(keyData);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")] // 'charCode' matches control.cs
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected internal override bool ProcessMnemonic(char charCode) {
// checking IsMnemonic is not necessary - toolstrip does this for us
PerformButtonClick();
return true;
}
///
///
/// called when the button portion of a split button is clicked
/// if there is a default item, this will route the click to the default item
///
protected virtual void OnButtonClick(System.EventArgs e) {
if (DefaultItem != null) {
DefaultItem.FireEvent(ToolStripItemEventType.Click);
}
EventHandler handler = (EventHandler)Events[EventButtonClick];
if (handler != null) handler(this, e);
}
///
///
/// called when the button portion of a split button is double clicked
/// if there is a default item, this will route the double click to the default item
///
public virtual void OnButtonDoubleClick(System.EventArgs e) {
if (DefaultItem != null) {
DefaultItem.FireEvent(ToolStripItemEventType.DoubleClick);
}
EventHandler handler = (EventHandler)Events[EventButtonDoubleClick];
if (handler != null) handler(this,e);
}
///
///
/// Inheriting classes should override this method to handle this event.
///
protected virtual void OnDefaultItemChanged(EventArgs e) {
InvalidateSplitButtonLayout();
if (CanRaiseEvents) {
EventHandler eh = Events[EventDefaultItemChanged] as EventHandler;
if (eh != null) {
eh(this, e);
}
}
}
///
///
/// Summary of OnMouseDown.
///
protected override void OnMouseDown(MouseEventArgs e) {
if (DropDownButtonBounds.Contains(e.Location)) {
if (e.Button == MouseButtons.Left) {
if (!DropDown.Visible) {
Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID");
openMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId();
this.ShowDropDown(/*mousePress = */true);
}
}
}
else {
SplitButtonButton.Push(true);
}
}
///
///
/// Summary of OnMouseUp.
///
protected override void OnMouseUp(MouseEventArgs e) {
if (!Enabled) {
return;
}
SplitButtonButton.Push(false);
if (DropDownButtonBounds.Contains(e.Location)) {
if (e.Button == MouseButtons.Left) {
if (DropDown.Visible) {
Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID");
byte closeMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId();
if (closeMouseId != openMouseId) {
openMouseId = 0; // reset the mouse id, we should never get this value from toolstrip.
ToolStripManager.ModalMenuFilter.CloseActiveDropDown(DropDown, ToolStripDropDownCloseReason.AppClicked);
Select();
}
}
}
}
Point clickPoint = new Point(e.X, e.Y);
if ((e.Button == MouseButtons.Left) && this.SplitButtonButton.Bounds.Contains(clickPoint)) {
bool shouldFireDoubleClick = false;
if (DoubleClickEnabled) {
long newTime = DateTime.Now.Ticks;
long deltaTicks = newTime - lastClickTime;
lastClickTime = newTime;
// use >= for cases where the succession of click events is so fast it's not picked up by
// DateTime resolution.
Debug.Assert(deltaTicks >= 0, "why are deltaticks less than zero? thats some mighty fast clicking");
// if we've seen a mouse up less than the double click time ago, we should fire.
if (deltaTicks >= 0 && deltaTicks < DoubleClickTicks) {
shouldFireDoubleClick = true;
}
}
if (shouldFireDoubleClick) {
OnButtonDoubleClick(new System.EventArgs());
// VSWhidbey 486983: if we actually fired DoubleClick - reset the lastClickTime.
lastClickTime = 0;
}
else {
OnButtonClick(new System.EventArgs());
}
}
}
///
protected override void OnMouseLeave(EventArgs e) {
openMouseId = 0; // reset the mouse id, we should never get this value from toolstrip.
SplitButtonButton.Push(false);
base.OnMouseLeave(e);
}
///
///
/// Summary of OnRightToLeftChanged.
///
protected override void OnRightToLeftChanged(EventArgs e) {
base.OnRightToLeftChanged(e);
InvalidateSplitButtonLayout();
}
///
///
/// Summary of OnPaint.
///
///
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
ToolStripRenderer renderer = this.Renderer;
if (renderer != null) {
InvalidateSplitButtonLayout();
Graphics g = e.Graphics;
renderer.DrawSplitButton(new ToolStripItemRenderEventArgs(g, this));
if ((DisplayStyle & ToolStripItemDisplayStyle.Image) != ToolStripItemDisplayStyle.None) {
renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, SplitButtonButtonLayout.ImageRectangle));
}
if ((DisplayStyle & ToolStripItemDisplayStyle.Text) != ToolStripItemDisplayStyle.None) {
renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, SplitButtonButton.Text, SplitButtonButtonLayout.TextRectangle, this.ForeColor, this.Font, SplitButtonButtonLayout.TextFormat));
}
}
}
public void PerformButtonClick() {
if (Enabled && Available) {
PerformClick();
OnButtonClick(EventArgs.Empty);
}
}
///
///
/// Resets the RightToLeft to be the default.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual void ResetDropDownButtonWidth() {
DropDownButtonWidth = DefaultDropDownButtonWidth;
}
///
/// Summary of SetDropDownBounds.
///
private void SetDropDownButtonBounds(Rectangle rect) {
dropDownButtonBounds = rect;
}
///
/// Determines if the property needs to be persisted.
///
[EditorBrowsable(EditorBrowsableState.Never)]
internal virtual bool ShouldSerializeDropDownButtonWidth() {
return (DropDownButtonWidth != DefaultDropDownButtonWidth);
}
///
/// This class represents the item to the left of the dropdown [ A |v] (e.g the "A")
/// It exists so that we can use our existing methods for text and image layout
/// and have a place to stick certain state information like pushed and selected
/// Note since this is NOT an actual item hosted on the Winbar - it wont get things
/// like MouseOver, wont be laid out by the ToolStrip, etc etc. This is purely internal
/// convenience.
///
private class ToolStripSplitButtonButton : ToolStripButton {
private ToolStripSplitButton owner = null;
public ToolStripSplitButtonButton(ToolStripSplitButton owner) {
this.owner = owner;
}
public override bool Enabled {
get {
return owner.Enabled;
}
set {
// do nothing
}
}
public override ToolStripItemDisplayStyle DisplayStyle {
get {
return owner.DisplayStyle;
}
set {
// do nothing
}
}
public override Padding Padding {
get {
return this.owner.Padding;
}
set {
// do nothing
}
}
public override ToolStripTextDirection TextDirection {
get {
return owner.TextDirection;
}
}
public override Image Image {
get {
if ((owner.DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image) {
return owner.Image;
}
else {
return null;
}
}
set {
// do nothing
}
}
public override bool Selected {
get {
if (owner != null) {
return owner.Selected;
}
return base.Selected;
}
}
public override string Text {
get {
if ((owner.DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) {
return owner.Text;
}
else {
return null;
}
}
set {
// do nothing
}
}
}
///
/// This class performs internal layout for the "split button button" portion of a split button.
/// Its main job is to make sure the inner button has the same parent as the split button, so
/// that layout can be performed using the correct graphics context.
///
private class ToolStripSplitButtonButtonLayout : ToolStripItemInternalLayout {
ToolStripSplitButton owner;
public ToolStripSplitButtonButtonLayout(ToolStripSplitButton owner) : base(owner.SplitButtonButton) {
this.owner = owner;
}
protected override ToolStripItem Owner {
get { return owner; }
}
protected override ToolStrip ParentInternal {
get {
return owner.ParentInternal;
}
}
public override Rectangle ImageRectangle {
get {
Rectangle imageRect = base.ImageRectangle;
// translate to ToolStripItem coordinates
imageRect.Offset(owner.SplitButtonButton.Bounds.Location);
return imageRect;
}
}
public override Rectangle TextRectangle {
get {
Rectangle textRect = base.TextRectangle;
// translate to ToolStripItem coordinates
textRect.Offset(owner.SplitButtonButton.Bounds.Location);
return textRect;
}
}
}
///
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class ToolStripSplitButtonAccessibleObject : ToolStripItem.ToolStripItemAccessibleObject {
private ToolStripSplitButton owner;
public ToolStripSplitButtonAccessibleObject(ToolStripSplitButton item) : base(item) {
owner = item;
}
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public override void DoDefaultAction() {
owner.PerformButtonClick();
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TraceXPathNavigator.cs
- WindowShowOrOpenTracker.cs
- ProxyWebPart.cs
- XmlObjectSerializerContext.cs
- DataServiceRequestException.cs
- DependencyPropertyValueSerializer.cs
- WindowsListBox.cs
- CompilerHelpers.cs
- AutoResizedEvent.cs
- WindowVisualStateTracker.cs
- AstTree.cs
- SqlUdtInfo.cs
- ResourceDescriptionAttribute.cs
- Decimal.cs
- MatchingStyle.cs
- ConstraintManager.cs
- WindowsListViewGroup.cs
- EventEntry.cs
- AnnotationComponentManager.cs
- SafeEventLogWriteHandle.cs
- hebrewshape.cs
- MSHTMLHost.cs
- TcpHostedTransportConfiguration.cs
- TreeNodeCollection.cs
- ExeConfigurationFileMap.cs
- MessageDecoder.cs
- XmlSchemaGroup.cs
- ObjectDataSourceFilteringEventArgs.cs
- EntitySetRetriever.cs
- XmlComment.cs
- BoolExpressionVisitors.cs
- PenLineCapValidation.cs
- DataGridViewSelectedCellCollection.cs
- TypeBuilder.cs
- DataGridColumnFloatingHeader.cs
- BookmarkOptionsHelper.cs
- Point3DAnimationUsingKeyFrames.cs
- MobileRedirect.cs
- Contracts.cs
- SymbolPair.cs
- ComPlusTypeValidator.cs
- CommandPlan.cs
- DatagridviewDisplayedBandsData.cs
- FamilyCollection.cs
- UIElementIsland.cs
- IteratorDescriptor.cs
- Listener.cs
- TemplatePropertyEntry.cs
- Positioning.cs
- SingleAnimationUsingKeyFrames.cs
- WebPartZone.cs
- HttpResponse.cs
- RowUpdatedEventArgs.cs
- ProxySimple.cs
- TypeConverterValueSerializer.cs
- CodeDirectoryCompiler.cs
- WebPartEditorCancelVerb.cs
- XmlNodeReader.cs
- ListViewUpdatedEventArgs.cs
- OperationInfoBase.cs
- Attachment.cs
- DisableDpiAwarenessAttribute.cs
- ToolStripItemRenderEventArgs.cs
- SplashScreenNativeMethods.cs
- D3DImage.cs
- ObjectStateManagerMetadata.cs
- MenuItem.cs
- MissingManifestResourceException.cs
- ValueUnavailableException.cs
- KeyedQueue.cs
- XmlEventCache.cs
- UpdatePanelTriggerCollection.cs
- DataTableMappingCollection.cs
- VirtualPathProvider.cs
- ApplicationException.cs
- CommandEventArgs.cs
- FormattedText.cs
- TraceHandlerErrorFormatter.cs
- XmlDocumentSchema.cs
- Environment.cs
- CodeArrayIndexerExpression.cs
- Brush.cs
- LocalizedNameDescriptionPair.cs
- HtmlInputReset.cs
- XmlNamespaceMapping.cs
- MappingSource.cs
- Asn1IntegerConverter.cs
- RegistryPermission.cs
- CounterCreationData.cs
- NavigationProgressEventArgs.cs
- TreeNodeStyle.cs
- HotCommands.cs
- PaperSource.cs
- SMSvcHost.cs
- WindowsToolbarItemAsMenuItem.cs
- BamlVersionHeader.cs
- FrameworkContentElement.cs
- XmlEventCache.cs
- RedirectionProxy.cs
- ScrollChangedEventArgs.cs