|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms.Design;
using System.Windows.Forms.Layout;
namespace System.Windows.Forms;
/// <summary>
/// A ToolStripButton that can display a popup.
/// </summary>
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
public partial class ToolStripDropDownButton : ToolStripDropDownItem
{
private bool _showDropDownArrow = true;
private byte _openMouseId;
/// <summary>
/// Constructs a ToolStripButton that can display a popup.
/// </summary>
public ToolStripDropDownButton()
{
Initialize();
}
public ToolStripDropDownButton(string? text)
: base(text, image: null, onClick: null)
{
Initialize();
}
public ToolStripDropDownButton(Image? image)
: base(text: null, image, onClick: null)
{
Initialize();
}
public ToolStripDropDownButton(string? text, Image? image)
: base(text, image, onClick: null)
{
Initialize();
}
public ToolStripDropDownButton(string? text, Image? image, EventHandler? onClick)
: base(text, image, onClick)
{
Initialize();
}
public ToolStripDropDownButton(string? text, Image? image, EventHandler? onClick, string? name)
: base(text, image, onClick, name)
{
Initialize();
}
public ToolStripDropDownButton(string? text, Image? image, params ToolStripItem[]? dropDownItems)
: base(text, image, dropDownItems)
{
Initialize();
}
protected override AccessibleObject CreateAccessibilityInstance()
{
return new ToolStripDropDownButtonAccessibleObject(this);
}
[DefaultValue(true)]
public new bool AutoToolTip
{
get => base.AutoToolTip;
set => base.AutoToolTip = value;
}
protected override bool DefaultAutoToolTip
{
get
{
return true;
}
}
[DefaultValue(true)]
[SRDescription(nameof(SR.ToolStripDropDownButtonShowDropDownArrowDescr))]
[SRCategory(nameof(SR.CatAppearance))]
public bool ShowDropDownArrow
{
get
{
return _showDropDownArrow;
}
set
{
if (_showDropDownArrow != value)
{
_showDropDownArrow = value;
InvalidateItemLayout(PropertyNames.ShowDropDownArrow);
}
}
}
/// <summary>
/// Creates an instance of the object that defines how image and text
/// gets laid out in the ToolStripItem
/// </summary>
private protected override ToolStripItemInternalLayout CreateInternalLayout()
{
return new ToolStripDropDownButtonInternalLayout(this);
}
protected override ToolStripDropDown CreateDefaultDropDown()
{
// AutoGenerate a ToolStrip DropDown - set the property so we hook events
return new ToolStripDropDownMenu(this, isAutoGenerated: true);
}
/// <summary>
/// Called by all constructors of ToolStripButton.
/// </summary>
private void Initialize()
{
SupportsSpaceKey = true;
}
/// <summary>
/// Overridden to invoke displaying the popup.
/// </summary>
protected override void OnMouseDown(MouseEventArgs e)
{
if ((Control.ModifierKeys != Keys.Alt) &&
(e.Button == MouseButtons.Left))
{
if (DropDown.Visible)
{
ToolStripManager.ModalMenuFilter.CloseActiveDropDown(DropDown, ToolStripDropDownCloseReason.AppClicked);
}
else
{
// opening should happen on mouse down.
Debug.Assert(ParentInternal is not null, "Parent is null here, not going to get accurate ID");
_openMouseId = (ParentInternal is null) ? (byte)0 : ParentInternal.GetMouseId();
ShowDropDown(/*mousePush =*/true);
}
}
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
if ((Control.ModifierKeys != Keys.Alt) &&
(e.Button == MouseButtons.Left))
{
Debug.Assert(ParentInternal is not null, "Parent is null here, not going to get accurate ID");
byte closeMouseId = (ParentInternal is 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();
}
}
base.OnMouseUp(e);
}
protected override void OnMouseLeave(EventArgs e)
{
_openMouseId = 0; // reset the mouse id, we should never get this value from toolstrip.
base.OnMouseLeave(e);
}
/// <summary>
/// Inheriting classes should override this method to handle this event.
/// </summary>
protected override void OnPaint(PaintEventArgs e)
{
if (Owner is not null)
{
ToolStripRenderer renderer = Renderer!;
Graphics g = e.Graphics;
renderer.DrawDropDownButtonBackground(new ToolStripItemRenderEventArgs(e.Graphics, this));
if ((DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image)
{
renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, InternalLayout.ImageRectangle));
}
if ((DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text)
{
renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, Text, InternalLayout.TextRectangle, ForeColor, Font, InternalLayout.TextFormat));
}
if (ShowDropDownArrow)
{
Rectangle dropDownArrowRect = (InternalLayout is ToolStripDropDownButtonInternalLayout layout) ? layout.DropDownArrowRect : Rectangle.Empty;
Color arrowColor;
if (Selected && !Pressed && SystemInformation.HighContrast)
{
arrowColor = Enabled ? SystemColors.HighlightText : SystemColors.ControlDark;
}
else
{
arrowColor = Enabled ? SystemColors.ControlText : SystemColors.ControlDark;
}
renderer.DrawArrow(new ToolStripArrowRenderEventArgs(g, this, dropDownArrowRect, arrowColor, ArrowDirection.Down));
}
}
}
protected internal override bool ProcessMnemonic(char charCode)
{
// checking IsMnemonic is not necessary - toolstrip does this for us.
if (HasDropDownItems)
{
Select();
ShowDropDown();
return true;
}
return false;
}
}
|