|
//------------------------------------------------------------------------------
// <copyright file="ToolStripDropDown.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Windows.Forms {
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Globalization;
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown"]/*' />
/// <devdoc>
/// Summary of ToolStripDropDown.
/// </devdoc>
[Designer("System.Windows.Forms.Design.ToolStripDropDownDesigner, " + AssemblyRef.SystemDesign)]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
public class ToolStripDropDown : ToolStrip {
private ToolStripItem ownerItem = null;
private bool isAutoGenerated = false;
private Point dropDownLocation = Point.Empty;
private bool dropShadowEnabled = true;
private bool autoClose = true;
private bool autoSize = true;
private int countDropDownItemsAssignedTo = 0; // the number of dropdown items using this as their dropdown..
private BitVector32 state = new BitVector32();
private Point displayLocation = new Point(0,0);
private bool saveSourceControl = false;
private ToolStripDropDownDirection childDropDownDirection = ToolStripDropDownDirection.Default;
private ToolStripDropDownCloseReason closeReason = ToolStripDropDownCloseReason.AppFocusChange;
private static readonly int PropOpacity = PropertyStore.CreateKey();
private static readonly int PropDDRightToLeft = PropertyStore.CreateKey();
private static readonly int PropSourceControl = PropertyStore.CreateKey();
private static readonly object EventOpening = new object();
private static readonly object EventOpened = new object();
private static readonly object EventClosed = new object();
private static readonly object EventClosing = new object();
private static readonly object ToolStripParkingWindowKey = new object();
private static readonly Padding defaultPadding = new Padding(1, 2, 1, 2);
private Padding scaledDefaultPadding = defaultPadding;
#if DEBUG
internal static TraceSwitch DropDownActivateDebug = new TraceSwitch("DropDownActivateDebug", "Debug activation code for dropDown controls");
internal static TraceSwitch DropDownDebugBounds = new TraceSwitch("DropDownDebugBounds", "Debug GetDropDownBounds");
static readonly BooleanSwitch AlwaysRestrictWindows = new BooleanSwitch("AlwaysRestrictWindows", "Always make Form classes behave as though they are restricted");
#else
internal static TraceSwitch DropDownActivateDebug;
internal static TraceSwitch DropDownDebugBounds;
#endif
private static readonly int stateLayered = BitVector32.CreateMask();
private static readonly int stateAllowTransparency = BitVector32.CreateMask(stateLayered);
private static readonly int stateIsRestrictedWindow = BitVector32.CreateMask(stateAllowTransparency);
private static readonly int stateIsRestrictedWindowChecked = BitVector32.CreateMask(stateIsRestrictedWindow);
private static readonly int stateNotWorkingAreaConstrained = BitVector32.CreateMask(stateIsRestrictedWindowChecked);
private static readonly int stateInSetVisibleCore = BitVector32.CreateMask(stateNotWorkingAreaConstrained);
/// SECREVIEW
/// ToolStripDropDown security notes
/// Key ideas:
/// AllWindowsPermission is required to get keystrokes, obscure the taskbar, prevent the dropdown from closing.
///
/// A. Disallow ControlHost items, both shipped and user created via UiPermission.AWP. We'd simply not display these items in the internet / dropdown case.
/// B. Disallow AutoClose == false and ignore cancelable closing event param. This makes it impossible to enter more than one keystroke and not cause dropdown dismissal.
/// C. Restrict keystroke handling events. We would route WM_KKEY* to DefWndProc, and because Control.WndProc would be skipped, the following events would not be raised:
/// On/KeyUp/On/KeyDown/On/KeyPress
/// D. Ensure proper link and inheritancedemands on
/// ProcessKeyPreview/ProcessDialogKey/ProcessCmdKey/ProcessKeyMessage/PreProcessMessage/WndProc
/// E. Ensure proper inheritance demands on
/// IsInputKey/IsInputChar
/// F. Prevent double mnemonic evaluation on DropDowns (another way of getting keyboard input by having hidden items)
/// Protect ProcessMnemonic.
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.ToolStripDropDown"]/*' />
/// <devdoc>
/// Summary of ToolStripDropDown.
/// </devdoc>
public ToolStripDropDown() {
if (DpiHelper.EnableToolStripHighDpiImprovements) {
scaledDefaultPadding = DpiHelper.LogicalToDeviceUnits(defaultPadding);
}
// SECURITY NOTE: The IsRestrictedWindow check is done once and cached. We force it to happen here
// since we want to ensure the check is done on the code that constructs the ToolStripDropDown.
bool temp = IsRestrictedWindow;
this.SuspendLayout();
Initialize();
this.ResumeLayout(false);
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.ToolStripDropDown2"]/*' />
/// <devdoc>
/// Summary of ToolStripDropDown.
/// </devdoc>
/// <param name=ownerItem></param>
internal ToolStripDropDown(ToolStripItem ownerItem): this() {
this.ownerItem = ownerItem;
}
internal ToolStripDropDown(ToolStripItem ownerItem, bool isAutoGenerated) : this(ownerItem) {
this.isAutoGenerated = isAutoGenerated;
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new bool AllowItemReorder {
get {
return base.AllowItemReorder;
}
set {
base.AllowItemReorder = value;
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.AllowTransparency"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>
/// Gets or sets
/// a value indicating whether the opacity of the form can be
/// adjusted.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
SRDescription(SR.ControlAllowTransparencyDescr)
]
public bool AllowTransparency {
get {
return state[stateAllowTransparency];
}
set {
if (value != (state[stateAllowTransparency]) &&
OSFeature.Feature.IsPresent(OSFeature.LayeredWindows)) {
state[stateAllowTransparency] = value;
state[stateLayered] = state[stateAllowTransparency];
UpdateStyles();
if (!value) {
if (Properties.ContainsObject(PropOpacity)) {
Properties.SetObject(PropOpacity, (object)1.0f);
}
UpdateLayered();
}
}
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public override AnchorStyles Anchor {
get {
return base.Anchor;
}
set {
base.Anchor = value;
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.AutoSize"]/*' />
[DefaultValue(true)]
public override bool AutoSize {
get {
return autoSize;
}
set {
if (autoSize != value) {
autoSize = value;
// we shadow CommonProperties
LayoutTransaction.DoLayout(this,this,PropertyNames.AutoSize);
OnAutoSizeChanged(EventArgs.Empty);
}
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.AutoClose"]/*' />
/// <devdoc>
/// specifies whether the dropdown should automatically close when the dropdown has lost
/// activation. If you want a dropdown that always stays open, specify AutoClose = false;
/// </devdoc>
[
DefaultValue(true),
SRCategory(SR.CatBehavior),
SRDescription(SR.ToolStripDropDownAutoCloseDescr)
]
public bool AutoClose {
get {
return autoClose;
}
set {
// SECREVIEW - to be honored, you must have AllWindowsPermission. See SetVisibleCore
if (autoClose != value) {
autoClose = value;
ApplyTopMost(/*topMost=*/!autoClose);
}
}
}
[Browsable(false)]
public new event EventHandler BackgroundImageChanged {
add {
base.BackgroundImageChanged += value;
}
remove {
base.BackgroundImageChanged -= value;
}
}
[Browsable(false)]
public new event EventHandler BackgroundImageLayoutChanged {
add {
base.BackgroundImageLayoutChanged += value;
}
remove {
base.BackgroundImageLayoutChanged -= value;
}
}
[Browsable(false)]
public new event EventHandler BindingContextChanged {
add {
base.BindingContextChanged += value;
}
remove {
base.BindingContextChanged -= value;
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.CanOverflow"]/*' />
[DefaultValue(false),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)]
public new bool CanOverflow {
get {
return base.CanOverflow;
}
set {
base.CanOverflow = value;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event UICuesEventHandler ChangeUICues {
add { base.ChangeUICues += value; }
remove { base.ChangeUICues -= value; }
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public new ContextMenu ContextMenu {
get { return base.ContextMenu; }
set { base.ContextMenu = value; }
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public new event EventHandler ContextMenuChanged {
add { base.ContextMenuChanged += value; }
remove { base.ContextMenuChanged -= value; }
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public new ContextMenuStrip ContextMenuStrip {
get { return base.ContextMenuStrip; }
set { base.ContextMenuStrip = value; }
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Always)]
public new event EventHandler ContextMenuStripChanged {
add { base.ContextMenuStripChanged += value; }
remove { base.ContextMenuStripChanged -= value; }
}
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.CreateParams"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para>
/// This is called when creating a window. Inheriting classes can overide
/// this to add extra functionality, but should not forget to first call
/// base.CreateParams() to make sure the control continues to work
/// correctly.
/// </para>
/// </devdoc>
protected override CreateParams CreateParams {
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
get {
CreateParams cp = base.CreateParams;
// If we're using themes then go ahead
if (DropShadowEnabled) {
cp.ClassStyle |= NativeMethods.CS_DROPSHADOW;
}
// we're a borderless menuless control with no min/max boxes
// we dont want to show in the taskbar either
//Q205158 HOWTO: Prevent a Window from Appearing on the Taskbar
//Give the window the WS_EX_TOOLWINDOW extended style, and remove the WS_EX_APPWINDOW style. As a side effect, the window will have a smaller caption than a normal window.
//Give the window the WS_POPUP style and make it owned by a hidden window. (Form)
cp.Style &= ~(NativeMethods.WS_CAPTION | NativeMethods.WS_CLIPSIBLINGS); /* no caption, no siblings */
cp.ExStyle &= ~(NativeMethods.WS_EX_APPWINDOW); /* show in taskbar = false */
// | NativeMethods.WS_EX_TOOLWINDOW
cp.Style |= (TopLevel) ? NativeMethods.WS_POPUP : NativeMethods.WS_CHILD;
cp.ExStyle |= (NativeMethods.WS_EX_CONTROLPARENT); /* show in taskbar = false */
bool topLevel = TopLevel;
// opacity
if (topLevel && (state[stateLayered])) {
cp.ExStyle |= NativeMethods.WS_EX_LAYERED;
}
else if (topLevel) {
//From MSDN: Menus, dialog boxes, and combo list boxes have the CS_SAVEBITS style. When you use this style for a window,
//Windows saves a bitmap copy of the screen image that the window obscures. First, Windows asks the display driver to save the bits.
//If the display driver has enough memory, it saves the bits for Windows. If the display driver does not have enough memory, Window
//saves the bits itself as a bitmap in global memory and also uses some of User's local heap for housekeeping structures for each window.
//When the application removes the window, Windows can restore the screen image quickly by using the stored bits.
cp.ClassStyle |= NativeMethods.CS_SAVEBITS;
}
else if (!topLevel) {
cp.Style |= NativeMethods.WS_CLIPSIBLINGS;
}
// We're turning off CLIPSIBLINGS because in the designer the elements of the form beneath
// are actually sibling controls. We want to paint right over them as if we were a toplevel window.
return cp;
}
}
/// <include file='doc\Control.uex' path='docs/doc[@for="Control.DefaultPadding"]/*' />
protected override Padding DefaultPadding {
get { return scaledDefaultPadding; }
}
/// <devdoc> We want this to default to true... This way tooltips on overflows and custom dropdowns will show.
/// Since menu items don't show tooltips by default we can savely leave it on </devdoc>
protected override bool DefaultShowItemToolTips {
get {
return true;
}
}
protected override DockStyle DefaultDock {
get {
return DockStyle.None;
}
}
public override ToolStripDropDownDirection DefaultDropDownDirection {
get {
if (childDropDownDirection == ToolStripDropDownDirection.Default) {
return (RightToLeft == RightToLeft.Yes)? ToolStripDropDownDirection.Left : ToolStripDropDownDirection.Right;
}
return childDropDownDirection;
}
set {
childDropDownDirection = value;
base.DefaultDropDownDirection = value;
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.Dock"]/*' />
[
DefaultValue(DockStyle.None),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Always)]
public override DockStyle Dock {
get {
return base.Dock;
}
set{
base.Dock = value;
}
}
/// changed the browsable attribute
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
public new event EventHandler DockChanged {
add {
base.DockChanged += value;
}
remove {
base.DockChanged -= value;
}
}
/// <devdoc>
/// Returns an owner window that can be used to
/// own a drop down.
/// </devdoc>
internal override NativeWindow DropDownOwnerWindow {
get {
// Re-use the drop down owner from our parenting
// tool strip if we can.
if (ownerItem != null && ownerItem.Owner != null) {
return ownerItem.Owner.DropDownOwnerWindow;
}
return base.DropDownOwnerWindow;
}
}
/// <include file='doc\ToolStripPopup.uex' path='docs/doc[@for="ToolStripDropDown.DropShadowEnabled"]/*' />
public bool DropShadowEnabled {
get {
// VSWhidbey 338272 - DropShadows are only supported on TopMost windows
// due to the flakeyness of the way it's implemented in the OS. (Non toplevel
// windows can have parts of the shadow disappear because another window can get
// sandwiched between the SysShadow window and the dropdown.)
return dropShadowEnabled && TopMost && DisplayInformation.IsDropShadowEnabled;
}
set {
if (dropShadowEnabled != value) {
dropShadowEnabled = value;
if (IsHandleCreated && !DesignMode) {
RecreateHandle();
}
}
}
}
[SRCategory(SR.CatAction), SRDescription(SR.ToolStripDropDownClosedDecr)]
public event ToolStripDropDownClosedEventHandler Closed {
add {
Events.AddHandler(EventClosed, value);
}
remove {
Events.RemoveHandler(EventClosed, value);
}
}
[SRCategory(SR.CatAction), SRDescription(SR.ToolStripDropDownClosingDecr)]
public event ToolStripDropDownClosingEventHandler Closing {
add {
Events.AddHandler(EventClosing, value);
}
remove {
Events.RemoveHandler(EventClosing, value);
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event EventHandler Enter {
add { base.Enter += value; }
remove { base.Enter -= value; }
}
public override Font Font {
get {
if (this.IsFontSet()) {
return base.Font;
}
// if the FONT isnt set, then return our owner item's font.
if (IsAutoGenerated && OwnerItem != null) {
return OwnerItem.Font;
}
return base.Font;
}
set {
base.Font = value;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event EventHandler FontChanged {
add { base.FontChanged += value; }
remove { base.FontChanged -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler ForeColorChanged {
add { base.ForeColorChanged += value; }
remove { base.ForeColorChanged -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event GiveFeedbackEventHandler GiveFeedback {
add { base.GiveFeedback += value; }
remove { base.GiveFeedback -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new ToolStripGripDisplayStyle GripDisplayStyle {
get {
return base.GripDisplayStyle;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new Rectangle GripRectangle {
get {
return base.GripRectangle;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new Padding GripMargin{
get {
return base.GripMargin;
}
set {
base.GripMargin = value;
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.GripStyle"]/*' />
[DefaultValue(ToolStripGripStyle.Hidden),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)]
public new ToolStripGripStyle GripStyle {
get {
return base.GripStyle;
}
set {
base.GripStyle = value;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
[SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly")] //Everett
new public event HelpEventHandler HelpRequested {
add { base.HelpRequested += value; }
remove { base.HelpRequested -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
public new event EventHandler ImeModeChanged {
add { base.ImeModeChanged += value; }
remove { base.ImeModeChanged -= value; }
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.IsAutoGenerated"]/*' />
/// <devdoc>
/// determines whether this dropdown was autogenerated.
/// </devdoc>
[Browsable(false)]
public bool IsAutoGenerated {
get {
return isAutoGenerated;
}
}
internal bool IsAssignedToDropDownItem {
get {
return IsAutoGenerated || (countDropDownItemsAssignedTo > 0);
}
}
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.IsRestrictedWindow"]/*' />
/// <internalonly/>
/// <devdoc>
/// <para> Determines if this form should display a warning banner
/// when the form is displayed in an unsecure mode.</para>
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)]
internal bool IsRestrictedWindow {
get {
/// SECREVIEW: make sure to keep changes here in sync with Form.IsRestrictedWindow
if (!state[stateIsRestrictedWindowChecked]) {
state[stateIsRestrictedWindowChecked] = true;
state[stateIsRestrictedWindow] = false;
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "Checking for restricted window...");
Debug.Indent();
#if DEBUG
if (AlwaysRestrictWindows.Enabled) {
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "Always restricted switch is on...");
state[stateIsRestrictedWindow] = true;
Debug.Unindent();
return true;
}
#endif
try {
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "WindowAdornmentModification Demanded");
IntSecurity.WindowAdornmentModification.Demand();
}
catch {
Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "Caught exception, we are restricted...");
state[stateIsRestrictedWindow] = true;
}
Debug.Unindent();
}
return state[stateIsRestrictedWindow];
}
}
internal override Size ImageScalingSizeInternal {
get {
if (IsAutoGenerated && OwnerToolStrip != null) {
return OwnerToolStrip.ImageScalingSizeInternal;
}
return base.ImageScalingSizeInternal;
}
set {
base.ImageScalingSizeInternal = value;
}
}
internal override bool KeyboardActive {
get {
// ripple up the chain until we get the topmost toolstrip (usually the main menu strip is the one we care about)
ToolStrip ownerToolStrip = OwnerToolStrip;
if (ownerToolStrip != null) {
return ownerToolStrip.KeyboardActive;
}
return base.KeyboardActive;
}
set {
base.KeyboardActive = value;
// ripple up the chain until we get the topmost toolstrip (usually the main menu strip is the one we care about)
ToolStrip ownerToolStrip = OwnerToolStrip;
if (ownerToolStrip != null) {
ownerToolStrip.KeyboardActive = value;
}
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event KeyEventHandler KeyDown {
add { base.KeyDown += value; }
remove { base.KeyDown -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event KeyPressEventHandler KeyPress {
add { base.KeyPress += value; }
remove { base.KeyPress -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event KeyEventHandler KeyUp {
add { base.KeyUp += value; }
remove { base.KeyUp -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
public new event EventHandler Leave {
add { base.Leave += value; }
remove { base.Leave -= value; }
}
/// <devdoc>
/// Override Location to make it hidden from the user in the designer
/// </devdoc>
[
EditorBrowsable(EditorBrowsableState.Never),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Browsable(false)
]
public new Point Location {
get {
return base.Location;
}
set {
base.Location = value;
}
}
[SRCategory(SR.CatAction), SRDescription(SR.ToolStripDropDownOpeningDescr)]
public event CancelEventHandler Opening {
add {
Events.AddHandler(EventOpening, value);
}
remove {
Events.RemoveHandler(EventOpening, value);
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.Opened"]/*' />
/// <devdoc>
/// <para>Occurs when the control is clicked.</para>
/// </devdoc>
[SRCategory(SR.CatAction), SRDescription(SR.ToolStripDropDownOpenedDescr)]
public event EventHandler Opened {
add {
Events.AddHandler(EventOpened, value);
}
remove {
Events.RemoveHandler(EventOpened, value);
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.MaxItemSize"]/*' />
protected internal override Size MaxItemSize {
get {
return Screen.GetWorkingArea(this.Bounds).Size - this.Padding.Size;
}
}
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.Opacity"]/*' />
/// <devdoc>
/// Determines the opacity of the form. This can only be set on top level
/// controls. Opacity requires Windows 2000 or later, and is ignored on earlier
/// operating systems.
/// </devdoc>
[
SRCategory(SR.CatWindowStyle),
TypeConverterAttribute(typeof(OpacityConverter)),
SRDescription(SR.FormOpacityDescr),
DefaultValue(1.0),
Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)
]
public double Opacity {
get {
object opacity = Properties.GetObject(PropOpacity);
if (opacity != null) {
return Convert.ToDouble(opacity, CultureInfo.InvariantCulture);
}
else {
return 1.0f;
}
}
set {
if (IsRestrictedWindow) {
value = Math.Max(value, .50f);
}
if (value > 1.0) {
value = 1.0f;
}
else if (value < 0.0) {
value = 0.0f;
}
Properties.SetObject(PropOpacity, value);
bool oldLayered = (state[stateLayered]);
if (OpacityAsByte < 255 && OSFeature.Feature.IsPresent(OSFeature.LayeredWindows))
{
AllowTransparency = true;
state[stateLayered] = true;
}
else
{
state[stateLayered] = false;
}
if (oldLayered != (state[stateLayered]))
{
UpdateStyles();
}
UpdateLayered();
}
}
private byte OpacityAsByte {
get {
return (byte)(Opacity * 255.0f);
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new ToolStripOverflowButton OverflowButton {
get {
return base.OverflowButton;
}
}
/// <include file='doc\ToolStripPopup.uex' path='docs/doc[@for="ToolStripDropDown.OwnerItem"]/*' />
/// <devdoc>
/// Summary of OwnerItem.
/// </devdoc>
[DefaultValue(null), Browsable(false)]
public ToolStripItem OwnerItem {
get { return ownerItem; }
set {
if (ownerItem != value) {
Font originalFont = this.Font;
RightToLeft startRightToLeft = this.RightToLeft;
ownerItem = value;
// RESET ambient properties
if (!originalFont.Equals(Font)) {
OnOwnerItemFontChanged(EventArgs.Empty);
}
if (ownerItem != null && RightToLeftInherited && startRightToLeft != this.RightToLeft) {
using (new LayoutTransaction(this,this,PropertyNames.RightToLeft)) {
OnRightToLeftChanged(EventArgs.Empty);
}
}
}
}
}
internal ToolStripDropDownItem OwnerDropDownItem {
get { return OwnerItem as ToolStripDropDownItem; }
}
internal ToolStrip OwnerToolStrip {
get {
if (ownerItem != null) {
ToolStrip owner = ownerItem.ParentInternal;
if (owner != null) {
return owner;
}
// might not actually be placed on the overflow, just check for sure.
if (ownerItem.Placement == ToolStripItemPlacement.Overflow && ownerItem.Owner != null) {
return ownerItem.Owner.OverflowButton.DropDown;
}
if (owner == null) {
return ownerItem.Owner;
}
}
return null;
}
}
/// <include file='doc\ContextMenuStrip.uex' path='docs/doc[@for="ContextMenuStrip.Region"]/*' />
/// <devdoc>
/// Hide the Region Property
/// </devdoc>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public Region Region {
get {
return base.Region;
}
set {
base.Region = value;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event EventHandler RegionChanged {
add { base.RegionChanged += value; }
remove { base.RegionChanged -= value; }
}
internal virtual bool RequiresScrollButtons {
get {
return false;
}
set {
Debug.Fail("You can't set this except on ToolStripDropDownMenu");
}
}
[
SRCategory(SR.CatAppearance),
Localizable(true),
AmbientValue(RightToLeft.Inherit),
SRDescription(SR.ControlRightToLeftDescr)
]
public override RightToLeft RightToLeft {
get {
// our inheritance is from our owner item.
if (RightToLeftInherited) {
if (SourceControlInternal != null) {
return SourceControlInternal.RightToLeft;
}
if (OwnerItem != null) {
return OwnerItem.RightToLeft;
}
}
return base.RightToLeft;
}
set {
base.RightToLeft = value;
}
}
private bool RightToLeftInherited {
get {
// fish out of control's property store whether or not RTL was set, if it's set to inherit.
return !ShouldSerializeRightToLeft();
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event ScrollEventHandler Scroll {
add { base.Scroll += value; }
remove { base.Scroll -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new bool Stretch {
get {
return base.Stretch;
}
set {
base.Stretch = value;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
new public event EventHandler StyleChanged {
add { base.StyleChanged += value; }
remove { base.StyleChanged -= value; }
}
internal Control SourceControlInternal {
get {
return Properties.GetObject(PropSourceControl) as Control;
}
set{
Properties.SetObject(PropSourceControl, value);
}
}
internal override int ShowParams {
get {
return NativeMethods.SW_SHOWNOACTIVATE;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler TabStopChanged {
add { base.TabStopChanged += value; }
remove { base.TabStopChanged -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler TextChanged {
add { base.TextChanged += value; }
remove { base.TextChanged -= value; }
}
[
Browsable(false),
DefaultValue(ToolStripTextDirection.Horizontal),
SRDescription(SR.ToolStripTextDirectionDescr),
SRCategory(SR.CatAppearance)
]
public override ToolStripTextDirection TextDirection {
get {
return base.TextDirection;
}
set {
base.TextDirection = value;
}
}
//Consistency: match casing of Form.TopMost, which shipped in Everett, even though it's wrong
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly")]
protected virtual bool TopMost
{
get { return true; }
}
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.TopLevel"]/*' />
[Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool TopLevel {
get {
return GetTopLevel();
}
set {
//
if (value != GetTopLevel()) {
SetTopLevelInternal(value);
SetTopLevelStyle(value);
}
}
}
// public Color TransparencyKey {
// This property intentionally not available for ToolStripDropDown
// it's not robust enough for our needs
// }
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.TabIndex"]/*' />
/// VSWhidbey 233498: override base TabIndex property in order to avoid serialization
/// (since a dropdown shouldn't participate in the taborder...)
[
EditorBrowsable(EditorBrowsableState.Never),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
Browsable(false)
]
public new int TabIndex {
get {
return base.TabIndex;
}
set {
base.TabIndex = value;
}
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
SRCategory(SR.CatPropertyChanged),
SRDescription(SR.ControlOnTabIndexChangedDescr)
]
public new event EventHandler TabIndexChanged {
add {
base.TabIndexChanged += value;
}
remove {
base.TabIndexChanged -= value;
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event EventHandler Validated {
add { base.Validated += value; }
remove { base.Validated -= value; }
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
new public event CancelEventHandler Validating {
add { base.Validating += value; }
remove { base.Validating -= value; }
}
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.Visible"]/*' />
/// VSWhidbey 233498: override base Visible property in order to control serialization by setting default value
[
SRCategory(SR.CatBehavior),
Localizable(true),
SRDescription(SR.ControlVisibleDescr),
DefaultValue(false),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public new bool Visible {
get {
return base.Visible;
}
set {
base.Visible = value;
}
}
// internally we use not so we dont have to initialize it.
internal bool WorkingAreaConstrained {
get {
if (state[stateNotWorkingAreaConstrained]) {
// SECREVIEW:
// We are constrained to the working area when we dont have AllWindows permission
return IsRestrictedWindow;
}
return true;
}
set {
bool notConstrained = !value;
state[stateNotWorkingAreaConstrained] = notConstrained;
}
}
internal void AssignToDropDownItem() {
countDropDownItemsAssignedTo++;
}
internal void AdjustSize() {
Size size = GetSuggestedSize();
if (size != this.Size) {
this.Size = size;
}
}
private void ApplyTopMost(bool topMost) {
if (TopMost) {
HandleRef topMostFlag = (topMost) ? NativeMethods.HWND_TOPMOST : NativeMethods.HWND_NOTOPMOST;
SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), topMostFlag, 0, 0, 0, 0,
NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOACTIVATE);
}
}
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.Dispose"]/*' />
protected override void Dispose(bool disposing) {
if (disposing) {
SourceControlInternal = null;
}
base.Dispose(disposing);
}
private void CancelAutoExpand() {
ToolStrip toplevelOwnerToolStrip = GetToplevelOwnerToolStrip();
if (toplevelOwnerToolStrip != null) {
toplevelOwnerToolStrip.MenuAutoExpand = false;
}
}
internal override bool CanProcessMnemonic() {
// VSWhidbey 515812: Dont let mnemonics act as keyboard input in IE in the internet.
if (IsRestrictedWindow && !Application.MessageLoop) {
return false;
}
return base.CanProcessMnemonic();
}
/// <include file='doc\ToolStrip.uex' path='docs/doc[@for="ToolStrip.CreateAccessibilityInstance"]/*' />
protected override AccessibleObject CreateAccessibilityInstance() {
return new ToolStripDropDownAccessibleObject(this);
}
protected override LayoutSettings CreateLayoutSettings(ToolStripLayoutStyle style) {
LayoutSettings layoutSettings = base.CreateLayoutSettings(style);
if (style == ToolStripLayoutStyle.Flow) {
FlowLayoutSettings flowLayoutSettings = layoutSettings as FlowLayoutSettings;
flowLayoutSettings.FlowDirection = FlowDirection.TopDown;
flowLayoutSettings.WrapContents = false;
return flowLayoutSettings;
}
return layoutSettings;
}
protected override void CreateHandle() {
base.CreateHandle();
if (TopLevel) {
ReparentToDropDownOwnerWindow();
if (!AutoClose || !WorkingAreaConstrained) {
ApplyTopMost(true);
}
}
if (DesignMode) {
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, false);
}
}
public void Close() {
SetCloseReason(ToolStripDropDownCloseReason.CloseCalled);
this.Visible = false;
// we were the last one in the chain, roll out of menu mode.
if (ToolStripManager.ModalMenuFilter.GetActiveToolStrip() == null) {
ToolStripManager.ModalMenuFilter.ExitMenuMode();
}
}
private void ResetCloseReason() {
closeReason = ToolStripDropDownCloseReason.AppFocusChange;
}
internal void SetCloseReason(ToolStripDropDownCloseReason reason) {
closeReason = reason;
}
public void Close(ToolStripDropDownCloseReason reason) {
SetCloseReason(reason);
this.Visible = false;
}
internal override Rectangle ApplyBoundsConstraints(int suggestedX, int suggestedY, int proposedWidth, int proposedHeight) {
Rectangle adjustedBounds = base.ApplyBoundsConstraints(suggestedX, suggestedY, proposedWidth, proposedHeight);
// SECREVIEW VSWhidbey 430541 - place security size restrictions in non public/protected function
// to prevent custom IL from skipping restrictions in SetBoundsCore.
if (IsRestrictedWindow && TopMost) {
adjustedBounds = WindowsFormsUtils.ConstrainToScreenWorkingAreaBounds(adjustedBounds);
}
return adjustedBounds;
}
/// <devdoc>
/// Summary of GetBaseDropDownBounds.
/// </devdoc>
// called by ToolStripDropDownMenu,
internal Rectangle GetDropDownBounds(Rectangle suggestedBounds) {
Rectangle dropDownBounds;
if (TopLevel) {
Point screenPoint = Point.Empty;
if ((ownerItem != null) && (ownerItem is ToolStripDropDownItem)) {
screenPoint = ((ToolStripDropDownItem)ownerItem).DropDownLocation;
}
else {
screenPoint = suggestedBounds.Location;
}
Rectangle suggestedScreenBounds = new Rectangle(screenPoint, suggestedBounds.Size);
if (WorkingAreaConstrained) {
dropDownBounds = WindowsFormsUtils.ConstrainToScreenWorkingAreaBounds(suggestedScreenBounds);
}
else {
dropDownBounds = WindowsFormsUtils.ConstrainToScreenBounds(suggestedScreenBounds);
}
}
else {
Point parentClientPoint = Point.Empty;
if ((ownerItem != null) && (ownerItem is ToolStripDropDownItem) && (ParentInternal != null)) {
parentClientPoint = ParentInternal.PointToClient(((ToolStripDropDownItem)ownerItem).DropDownLocation);
}
else {
parentClientPoint = suggestedBounds.Location;
}
dropDownBounds = new Rectangle(parentClientPoint, suggestedBounds.Size);
}
Debug.WriteLineIf(DropDownDebugBounds.TraceVerbose, "DropDownBounds for " + suggestedBounds + "is" +dropDownBounds);
return dropDownBounds;
}
internal Rectangle CalculateDropDownLocation(Point start, ToolStripDropDownDirection dropDownDirection) {
Point offset = Point.Empty;
if (!IsHandleCreated) {
// PERF:
// if the handle isnt created yet, then we likely havent performed layout
// yet. force a layout here so that we get the correct size.
LayoutTransaction.DoLayout(this, this, PropertyNames.PreferredSize);
}
Rectangle dropDownBounds = new Rectangle(Point.Empty, GetSuggestedSize());
// calculate the offset from the upper left hand corner of the item.
switch (dropDownDirection) {
case ToolStripDropDownDirection.AboveLeft:
offset.X = - dropDownBounds.Width;
offset.Y = - dropDownBounds.Height;
break;
case ToolStripDropDownDirection.AboveRight:
offset.Y = - dropDownBounds.Height;
break;
case ToolStripDropDownDirection.BelowRight:
case ToolStripDropDownDirection.Right:
break;
case ToolStripDropDownDirection.BelowLeft:
case ToolStripDropDownDirection.Left:
offset.X = - dropDownBounds.Width;
break;
}
dropDownBounds.Location = new Point(start.X + offset.X, start.Y + offset.Y);
if (WorkingAreaConstrained) {
dropDownBounds = WindowsFormsUtils.ConstrainToScreenWorkingAreaBounds(dropDownBounds);
}
return dropDownBounds;
}
internal Size GetSuggestedSize() {
if (AutoSize) {
return GetPreferredSize(Size.Empty);
}
return this.Size;
}
/// <devdoc>
/// Returns the ToolStrip from which all the dropdowns started from. This can be null.
/// </devdoc>
internal override ToolStrip GetToplevelOwnerToolStrip() {
ToolStripDropDown topmost = GetFirstDropDown();
return (topmost.OwnerItem == null) ? null : topmost.OwnerToolStrip;
}
internal ToolStripItem GetToplevelOwnerItem() {
ToolStripDropDown topmost = GetFirstDropDown();
return topmost.OwnerItem;
}
internal override void HandleItemClicked(ToolStripItem dismissingItem) {
// Only clear the SourceControl if this is the last click.
if (!LocalAppContextSwitches.UseLegacyContextMenuStripSourceControlValue &&
this.ActiveDropDowns.Count == 0) {
// post processing after the click has happened.
SourceControlInternal = null;
}
base.HandleItemClicked(dismissingItem);
}
/// <devdoc>
/// Set some common properties
/// </devdoc>
internal virtual void Initialize() {
SetState(STATE_VISIBLE, false);
SetTopLevelInternal(true);
// VSWhidbey 82103 -- marking this as a modal form prevents it from being activated
// by the IMsoComponentManager, which will break keyboard routing in VS.
//
SetState(STATE_MODAL, true);
SetStyle(ControlStyles.ResizeRedraw, true);
this.UpdateStyles();
this.GripStyle = ToolStripGripStyle.Hidden;
this.CanOverflow = false;
this.LayoutStyle = ToolStripLayoutStyle.Flow;
this.MenuAutoExpand = true;
this.AutoSize = true;
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.OnClosed"]/*' />
/// <devdoc>
/// Summary of OnLayout.
/// </devdoc>
/// <param name=e></param>
protected virtual void OnClosed(ToolStripDropDownClosedEventArgs e){
if (IsHandleCreated) {
if (ownerItem == null || !ownerItem.IsInDesignMode)
{
AccessibilityNotifyClients(AccessibleEvents.SystemMenuPopupEnd, -1);
}
}
ToolStripDropDownClosedEventHandler handler = (ToolStripDropDownClosedEventHandler)Events[EventClosed];
if (handler != null) handler(this, e);
}
// SECREVIEW - for the "Cancel" to be honored, you must have AllWindowsPermission
// i.e. ToolStripDropDown.IsRestrictedWindow MUST be false.
// for more details see ToolStripDropDown.SetVisibleCore
protected virtual void OnClosing(ToolStripDropDownClosingEventArgs e) {
ToolStripDropDownClosingEventHandler handler = (ToolStripDropDownClosingEventHandler)Events[EventClosing];
if (handler != null) handler(this, e);
}
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.OnHandleCreated"]/*' />
/// <devdoc>
/// When our handle is being created, suspend the deactivation
/// portion of the WndProc, as we'll never be shown.
/// </devdoc>
protected override void OnHandleCreated(EventArgs e) {
UpdateStyles(); // get rid of WS_CAPTION style
base.OnHandleCreated(e);
UpdateLayered(); // update transparency
}
protected override void OnItemClicked(ToolStripItemClickedEventArgs e) {
try {
base.OnItemClicked(e);
}
finally {
ToolStripDropDownItem dismissingItem = e.ClickedItem as ToolStripDropDownItem;
if (AutoClose) {
if ((dismissingItem == null) // it's not a dropdownitem
|| (dismissingItem is ToolStripSplitButton && !dismissingItem.DropDown.Visible) // clicking on the split button button dismisses
|| !(dismissingItem.HasDropDownItems)) { // clicking on a item w/dropdown does not dismiss window
Close(ToolStripDropDownCloseReason.ItemClicked);
}
}
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.OnLayout"]/*' />
protected override void OnLayout(LayoutEventArgs e) {
// VSWhidbey 480533 it's important to size the dropdown first, then layout so that
// the layout engine and SetDisplayedItems know how big the container is.
AdjustSize();
base.OnLayout(e);
}
protected virtual void OnOpening(CancelEventArgs e){
CancelEventHandler handler = (CancelEventHandler)Events[EventOpening];
if (handler != null) handler(this, e);
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.OnOpened"]/*' />
/// <devdoc>
/// Summary of OnLayout.
/// </devdoc>
/// <param name=e></param>
protected virtual void OnOpened(System.EventArgs e) {
if (IsHandleCreated) {
if (ownerItem == null || !ownerItem.IsInDesignMode)
{
AccessibilityNotifyClients(AccessibleEvents.SystemMenuPopupStart, -1);
}
}
EventHandler handler = (EventHandler)Events[EventOpened];
if (handler != null) handler(this, e);
}
protected override void OnVisibleChanged(System.EventArgs e) {
if (this.Location != this.displayLocation) {
// If we adjusted the position from where the user wanted it,
// see if we can put it in the right location now that they've changed
// the items collection, and store where we actually have it.
// Just because this is the case doesn't mean that we need to do another
// another layout however.
this.Location = this.displayLocation;
this.displayLocation = this.Location;
}
if (AutoScroll || this.LayoutRequired) {
// the base here forces a layout... we really only want to do this the first
// time we pop the window... the subsequent times should be snappy.
base.OnVisibleChanged(e);
}
else {
this.SuspendLayout();
try {
// scrollable control forces a layout here for scrollbar reasons only
// since we toggle visibility a lot this is expensive. Let's be clever and
// not do it.
base.OnVisibleChanged(e);
}
finally {
this.ResumeLayout(false);
}
}
}
/// <include file='doc\WinBarPopup.uex' path='docs/doc[@for="ToolStripDropDown.OnParentChanged"]/*' />
protected override void OnParentChanged(System.EventArgs e) {
base.OnParentChanged(e);
Rectangle bounds = this.Bounds;
SetBoundsCore(bounds.X, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
}
protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs mea) {
base.OnMouseUp(mea);
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.OnMouseUp] mouse up outside of the toolstrip - this should dismiss the entire chain");
//VSWhidbey 384068 Menus should dismiss when you drag off
if (!ClientRectangle.Contains(mea.Location)) {
bool dismiss = true;
if (OwnerToolStrip != null && OwnerItem != null) {
if (OwnerItem.Bounds.Contains(WindowsFormsUtils.TranslatePoint(mea.Location, this, OwnerToolStrip))) {
dismiss = false; // dont dismiss if we clicked on our owner item
}
}
if (dismiss) {
DismissAll();
CancelAutoExpand();
}
}
}
internal void OnOwnerItemFontChanged(EventArgs e) {
if (this.IsAutoGenerated) {
using (new LayoutTransaction(this, OwnerItem, PropertyNames.Font)) {
OnFontChanged(e);
}
}
}
internal void SelectPreviousToolStrip() {
// snap the owner item before calling hide as non-auto created dropdowns will
// exit menu mode if there's no OwnerItem.
ToolStripItem itemOnPreviousMenuToSelect = this.OwnerItem;
this.Hide();
if (itemOnPreviousMenuToSelect != null) {
itemOnPreviousMenuToSelect.Select();
if (!AccessibilityImprovements.UseLegacyToolTipDisplay) {
KeyboardToolTipStateMachine.Instance.NotifyAboutGotFocus(itemOnPreviousMenuToSelect);
}
if (OwnerToolStrip != null) {
// make sure we send keyboard handling where we've just
// sent selection
if (!OwnerToolStrip.IsDropDown) {
if (ToolStripManager.ModalMenuFilter.GetActiveToolStrip() != OwnerToolStrip) {
ToolStripManager.ModalMenuFilter.SetActiveToolStrip(OwnerToolStrip);
}
// escape should cancel auto expansion
OwnerToolStrip.MenuAutoExpand = false;
// When the control cannot be select (TabStop), we can press "Tab" to
// navigate inside the owner toolstip. Otherwise, press "Tab" will leave
// the owner toolstrip so it should exit the menu mode.
if (OwnerToolStrip.CanSelect) {
ToolStripManager.ModalMenuFilter.ExitMenuMode();
}
}
}
}
else {
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.SelectPreviousToolStrip] No previous toolstrip to select - exiting menu mode.");
ToolStripManager.ModalMenuFilter.ExitMenuMode();
}
}
/// <devdoc>
/// this is where we handle navigation between the File,Edit,View dropdowns
/// if you have one of these dropdowns showing and you hit the arrow key
/// and it's not processed by the menu item
/// </devdoc>
internal override bool ProcessArrowKey(Keys keyCode) {
Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripDropDown.ProcessArrowKey] MenuTimer.Cancel called");
ToolStripMenuItem.MenuTimer.Cancel();
if (keyCode == Keys.Left || keyCode == Keys.Right) {
bool rightAligned = SystemInformation.RightAlignedMenus;
bool forward = (keyCode == Keys.Left && rightAligned) || (keyCode == Keys.Right && !rightAligned);
if (!IsFirstDropDown && !forward) {
// this is the case where you've casecaded out to a second level dropdown and you hit the back arrow
// key. In this case we want to just hide the current dropdown
this.Visible = false;
return true;
}
else {
bool closeOnHorizontalKey = false;
if (LayoutStyle == ToolStripLayoutStyle.Flow) {
closeOnHorizontalKey = FlowLayout.GetFlowDirection(this) == FlowDirection.TopDown && !FlowLayout.GetWrapContents(this);
}
if (closeOnHorizontalKey) {
ToolStrip toplevelToolStrip = GetToplevelOwnerToolStrip();
ToolStripItem rootItem = GetToplevelOwnerItem();
// This is the case where you need to open up the adjacent DropDown (File->Edit) menus because:
// - this is the toplevel ToolStripDropDown and you hit left or right
// - this is a non-toplevel ToolStripDropDown and you hit an arrow key in a direction
// of the cascade AND the current item has no cascading menu associated with it.
bool isOnOverflow = (OwnerItem != null && OwnerItem.IsOnOverflow);
if (forward || !isOnOverflow) {
SetCloseReason(ToolStripDropDownCloseReason.Keyboard);
DismissAll();
}
else if (isOnOverflow) {
// VSWhidbey 478068: going backwards should roll us up and our children but not the overflow.
Visible = false;
}
if (toplevelToolStrip != null && rootItem != null) {
if (ToolStripManager.ModalMenuFilter.GetActiveToolStrip() != toplevelToolStrip) {
ToolStripManager.ModalMenuFilter.SetActiveToolStrip(toplevelToolStrip);
}
toplevelToolStrip.SelectNextToolStripItem(rootItem,forward);
}
return true;
}
}
}
// get base behavior like up/down navigation.
return base.ProcessArrowKey(keyCode);
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.ProcessDialogKey"]/*' />
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected override bool ProcessDialogKey(Keys keyData) {
if (this.OwnerItem != null && this.OwnerItem.IsInDesignMode) {
return false;
}
if (AutoClose && Visible) {
if (ToolStripManager.IsMenuKey(keyData)) {
SetCloseReason(ToolStripDropDownCloseReason.Keyboard);
DismissAll();
ToolStrip toplevel = GetToplevelOwnerToolStrip();
if (toplevel != null) {
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown ProcessDialogKey]: Got Menu Key, finding toplevel toolstrip, calling RestoreFocus.");
toplevel.RestoreFocusInternal();
ToolStripManager.ModalMenuFilter.MenuKeyToggle = true;
}
ToolStripManager.ModalMenuFilter.ExitMenuMode();
return true;
}
else if ((keyData & Keys.KeyCode) == Keys.Escape) {
SetCloseReason(ToolStripDropDownCloseReason.Keyboard);
SelectPreviousToolStrip();
return true;
}
}
return base.ProcessDialogKey(keyData);
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected override bool ProcessDialogChar(char charCode) {
#if DEBUG
Debug.WriteLineIf(ControlKeyboardRouting.TraceVerbose, "ToolStripDropDown.ProcessDialogChar [" + charCode.ToString() + "]");
#endif
// since we're toplevel and arent a container control, we've got to do our own mnemonic handling.
//
if ((OwnerItem == null || OwnerItem.Pressed) && charCode != ' ') {
if (ProcessMnemonic(charCode)){
return true;
}
}
return base.ProcessDialogChar(charCode);
}
[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
protected internal override bool ProcessMnemonic(char charCode) {
if (!CanProcessMnemonic()) {
return false; // here for security see CanProcessMnemonic.
}
return base.ProcessMnemonic(charCode);
}
internal override void ProcessDuplicateMnemonic(ToolStripItem item, char charCode) {
if (!CanProcessMnemonic()) {
return; // here for security see CanProcessMnemonic.
}
if (item != null) {
// SECREVIEW
// We want to make sure that Mnemonics arent another way of getting keyboard
// input. Allowing double mnemonics to switch selection could effectively let you
// figure out what someone was typing into the window by checking the selected state
// of all of your items. Instead of switching selection, we'll just perform the click.
// ===> Assumes ToolStripItem.ProcessMnemonic is protected by AWP
if (IsRestrictedWindow) {
item.ProcessMnemonic(charCode); // execute the first click
}
else {
base.ProcessDuplicateMnemonic(item,charCode);
}
}
}
internal override void RecreateHandleCore() {
// If we're visible, then we'll have set our parent hwnd to the active control.
// That means that re-create handle will set it as our parent, but that's not what
// we want, since that means that from now on we'll be displayed in that controls
// client co-ordinates. To fix this, we first re-parent ourselves back to the
// hidden window, do the re-create, then set the parent again.
if (Visible) {
ReparentToDropDownOwnerWindow();
}
base.RecreateHandleCore();
if (Visible) {
ReparentToActiveToolStripWindow();
}
}
private void ResetDropShadowEnabled() {
DropShadowEnabled = true;
}
private void ReparentToActiveToolStripWindow() {
ToolStripManager.ModalMenuFilter.SetActiveToolStrip(this);
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT, ToolStripManager.ModalMenuFilter.ActiveHwnd);
}
private void ReparentToDropDownOwnerWindow() {
// when we're toplevel we need to parent ourselves to a hidden window
// this prevents a taskbar entry.
NativeWindow ownerWindow = DropDownOwnerWindow;
HandleRef ownerHandle = new HandleRef(ownerWindow, ownerWindow.Handle);
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT, ownerHandle);
}
internal override void ResetScaling(int newDpi) {
base.ResetScaling(newDpi);
CommonProperties.xClearPreferredSizeCache(this);
scaledDefaultPadding = DpiHelper.LogicalToDeviceUnits(defaultPadding, newDpi);
}
/// <devdoc>
/// VERY similar to Form.ScaleCore
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void ScaleCore(float dx, float dy) {
Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, GetType().Name + "::ScaleCore(" + dx + ", " + dy + ")");
SuspendLayout();
try {
//Get size values in advance to prevent one change from affecting another.
Size clientSize = ClientSize;
Size minSize = MinimumSize;
Size maxSize = MaximumSize;
ClientSize = ScaleSize(clientSize, dx, dy);
if (!MinimumSize.IsEmpty) {
MinimumSize = ScaleSize(minSize, dx, dy);
}
if (!MaximumSize.IsEmpty) {
MaximumSize = ScaleSize(maxSize, dx, dy);
}
ScaleDockPadding(dx, dy);
foreach(Control control in Controls) {
if (control != null) {
#pragma warning disable 618
control.Scale(dx, dy);
#pragma warning restore 618
}
}
}
finally {
ResumeLayout();
}
}
/// <include file='doc\Form.uex' path='docs/doc[@for="ToolStripDropDown.ScaleControl"]/*' />
/// <devdoc>
/// Scale this form. Form overrides this to enforce a maximum / minimum size.
/// </devdoc>
protected override void ScaleControl(SizeF factor, BoundsSpecified specified) {
base.ScaleControl(factor, specified);
Size minSize = MinimumSize;
Size maxSize = MaximumSize;
if (!MinimumSize.IsEmpty) {
MinimumSize = ScaleSize(minSize, factor.Width, factor.Height);
}
if (!MaximumSize.IsEmpty) {
MaximumSize = ScaleSize(maxSize, factor.Width, factor.Height);
}
}
/// <devdoc>
/// This is called when the ToolStripDropDownItem sets the DropDown property using CreateDefaultDropDown.
/// In this case, the IsAutoGenerated should return true.
/// </devdoc>
internal void SetAutoGeneratedInternal(bool autoGenerated)
{
this.isAutoGenerated = autoGenerated;
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.SetBoundsCore"]/*' />
/// <devdoc>
/// Sync sizes with the ToolStripDropDown
/// </devdoc>
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
Rectangle bounds = new Rectangle(x, y, width, height);
bounds = GetDropDownBounds(bounds);
base.SetBoundsCore(bounds.X, bounds.Y, bounds.Width, bounds.Height, specified);
}
private void SetTopLevelStyle(bool value) {
if (IsHandleCreated) {
// We need to swap they style bits on the window handle
// we could recreate the handle, but that seems rather expensive.
int styleFlags = WindowStyle;
if (value) {
// setting toplevel = true
styleFlags &= ~NativeMethods.WS_CHILD;
styleFlags |= NativeMethods.WS_POPUP;
}
else {
// this is a child window
styleFlags &= ~NativeMethods.WS_POPUP;
styleFlags |= NativeMethods.WS_CHILD;
}
WindowStyle = styleFlags;
}
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.SetVisibleCore"]/*' />
/// <devdoc>
/// Summary of SetVisibleCore.
/// </devdoc>
/// <param name=visible></param>
protected override void SetVisibleCore(bool visible) {
if (state[stateInSetVisibleCore]) {
return;
}
state[stateInSetVisibleCore] = true;
try {
if (visible) {
if (LayoutRequired) {
LayoutTransaction.DoLayout(this, this, PropertyNames.Visible);
}
bool openingEventCancelled = true; // assume that it's been cancelled so that if we throw we do nothing.
try {
// VSWhidbey 313920 - add opening event.
// Snap the foreground window BEFORE calling any user events so they dont have a
// chance to activate something else. This covers the case where someone handles the
// opening event and throws up a messagebox.
IntPtr foregroundWindow = UnsafeNativeMethods.GetForegroundWindow();
// Fire Opening event
// Cancellable event in which default value of e.Cancel depends on the number of displayed items >0.
//
CancelEventArgs openEventArgs = new CancelEventArgs(/*cancel=*/(DisplayedItems.Count == 0));
OnOpening(openEventArgs);
openingEventCancelled = openEventArgs.Cancel;
if (!openingEventCancelled) {
// do the actual work to open the window.
if (TopLevel) {
ReparentToActiveToolStripWindow();
}
// review: what is this used for?
if (OwnerToolStrip != null) {
OwnerToolStrip.ActiveDropDowns.Add(this);
// the act of showing this window can cause a spurious mouse move
// in the parent, make sure it retains where the mouse really was.
OwnerToolStrip.SnapMouseLocation();
// VSWhidbey 458967: make sure that mouse capture
// transitions between the owner and dropdown.
if (OwnerToolStrip.CaptureInternal) {
CaptureInternal = true;
}
}
base.SetVisibleCore(visible);
if (TopLevel){
ApplyTopMost(true);
}
else if (IsHandleCreated && SafeNativeMethods.IsWindowEnabled(new HandleRef(this, Handle))) {
SafeNativeMethods.SetWindowPos(new HandleRef(this, Handle), NativeMethods.HWND_TOP, 0, 0, 0, 0,
NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOSIZE | NativeMethods.SWP_NOACTIVATE);
}
}
}
finally {
// Fire Opened event
// fire the opened event only if we actually opened the control.
//
if (!openingEventCancelled) {
OnOpened(new EventArgs());
}
}
}
else {
if (GetVisibleCore()) {
ToolStripDropDownCloseReason reason = closeReason;
ResetCloseReason();
ToolStripDropDownClosingEventArgs e = new ToolStripDropDownClosingEventArgs(reason);
// Fire Closing Event
// Cancel is prepopulated based on AutoClose feature.
//
if (e.CloseReason != ToolStripDropDownCloseReason.CloseCalled) {
e.Cancel = !AutoClose;
}
else {
e.Cancel = false;
}
try {
OnClosing(e);
}
finally {
// SECREVIEW - When IsRestrictedWindow is true, you cannot cancel the closing of the ToolStripDropDown.
// You can set AutoClose = false and OnClosing(e.Cancel=true), but we will ignore it.
if (!e.Cancel || IsRestrictedWindow /*delay evaluate only in the case we need it*/) {
// setting to not visible. Dismiss our child drop downs, reset, set ourselves visible false.
DismissActiveDropDowns();
// VSWhidbey 480392 and Dev10 490127: make sure we cancel auto expansion on the root
ToolStrip topLevelToolStrip = GetToplevelOwnerToolStrip();
ToolStrip parentToolStrip = null;
if (this.OwnerItem != null) {
parentToolStrip = this.OwnerItem.ParentInternal;
}
// We don't consider reason == ToolStripDropDownCloseReason.Keyboard here.
// DropDown needs to be closed when Alt or ESC is pressed,
// but these two keys are handled in ToolStrip.RestoreFocusInternal()
// and ToolStripDropDown.SelectPreviousToolStrip() respectively,
// and ToolStrip.MenuAutoExpand of top level tool strip will be set false there.
// Left and Right keys may also close dropdown, but we don't need to
// set ToolStrip.MenuAutoExpand of top level tool strip to be false in such cases.
if ((reason == ToolStripDropDownCloseReason.AppClicked) ||
(reason == ToolStripDropDownCloseReason.ItemClicked) ||
(reason == ToolStripDropDownCloseReason.CloseCalled && topLevelToolStrip == parentToolStrip) ||
(reason == ToolStripDropDownCloseReason.AppFocusChange && topLevelToolStrip == parentToolStrip)) {
CancelAutoExpand();
}
// if this came through via a click event we should actually
// dismiss everyone in the chain. Other windows will recieve a
// close, closing event with reason AppFocusChange. This is by
// design since the item wasnt clicked on that window.
if (reason == ToolStripDropDownCloseReason.ItemClicked) {
// Preserve the SourceControl value up the chain.
this.saveSourceControl = true;
DismissAll();
// make sure that when we roll up, our owner item's selection is cleared.
ToolStripItem rootOwnerItem = GetToplevelOwnerItem();
if (rootOwnerItem != null) {
rootOwnerItem.Unselect();
}
ToolStripManager.ModalMenuFilter.RemoveActiveToolStrip(this);
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose,"[ToolStripDropDown.SetVisibleCore] Exiting menu mode because item clicked");
ToolStripManager.ModalMenuFilter.ExitMenuMode();
}
else {
ToolStripManager.ModalMenuFilter.RemoveActiveToolStrip(this);
}
// snap our bounds, we'll need it for some invalidation later.
Rectangle bounds = this.Bounds;
try {
base.SetVisibleCore(visible);
}
finally {
// remove ourselves from the active dropdown list.
if (OwnerToolStrip != null) {
OwnerToolStrip.ActiveDropDowns.Remove(this);
}
ActiveDropDowns.Clear();
// VSWhidbey 389244: if the user traps the click event and starts
// pumping their own messages by calling Application.DoEvents, we
// should release mouse capture.
if (CaptureInternal) {
CaptureInternal = false;
}
}
// Fire OnClosed.
// if you make VisibleChanged throw you dont get closed. Sorry.
ToolStripDropDownClosedEventArgs closedEventArgs = new ToolStripDropDownClosedEventArgs(reason);
OnClosed(closedEventArgs);
if (TopLevel && (!IsDisposed || !Disposing)) {
// Parent back up to our DropDownOwnerWindow.
ReparentToDropDownOwnerWindow();
}
if (!this.saveSourceControl) {
Debug.Assert(reason != ToolStripDropDownCloseReason.ItemClicked,
"Why are we resetting SourceControl on a click event?");
// VSWhidbey 475650: If we're not about to fire a Click event, reset SourceControl.
SourceControlInternal = null;
}
// Making ourselves look presentable:
// We may be about to invoke a click event here...
// if we're the topmost dropdown then invalidate our
// intersection with the toplevel toolstrip
if (!DesignMode && IsFirstDropDown && OwnerItem != null && TopLevel) {
ToolStrip toolStrip = GetToplevelOwnerToolStrip();
if (toolStrip != null && !(toolStrip.IsDisposed || toolStrip.Disposing)) {
// translate the bounds (already in screen coords) to toolstrip.
bounds.Location = toolStrip.PointToClient(bounds.Location);
// find the intersection with the client and use that to invalidate
bounds.Intersect(toolStrip.ClientRectangle);
if (bounds.Width > 0 && bounds.Height >0) {
toolStrip.Invalidate(bounds);
toolStrip.Update();
}
}
}
}
}
}
else {
ToolStripManager.ModalMenuFilter.RemoveActiveToolStrip(this);
}
}
}
finally {
state[stateInSetVisibleCore] = false;
this.saveSourceControl = false;
}
}
private bool ShouldSerializeDefaultDropDownDirection() {
return (childDropDownDirection != ToolStripDropDownDirection.Default);
}
/// <devdoc>
/// Updates the layered window attributes if the control
/// is in layered mode.
/// </devdoc>
private void UpdateLayered() {
if (state[stateLayered] && IsHandleCreated && TopLevel && OSFeature.Feature.IsPresent(OSFeature.LayeredWindows)) {
bool result;
result = UnsafeNativeMethods.SetLayeredWindowAttributes(new HandleRef(this, Handle), 0, OpacityAsByte, NativeMethods.LWA_ALPHA);
if (!result) {
throw new Win32Exception();
}
}
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public new void Show() {
// don't set displayLocation here, since all the other Show methods call this.
base.Show();
}
/// <include file='doc\ToolStripPopup.uex' path='docs/doc[@for="ToolStripDropDown.Show"]/*' />
/// <devdoc> show relative to control coordinates </devdoc>
public void Show(Control control, Point position) {
if (control == null) {
throw new ArgumentNullException("control");
}
SourceControlInternal = control;
// VSWhidbey 310328 - when we have no owner item and we're set to RTL.Inherit, translate the coordinates
// so that the menu looks like it's swooping from the other side
if (this.OwnerItem == null && control.RightToLeft == RightToLeft.Yes) {
AdjustSize();
position.Offset(control.IsMirrored ? Width : -Width, 0);
}
this.displayLocation = control.PointToScreen(position);
this.Location = this.displayLocation;
ShowCore();
}
public void Show(Control control, Point position, ToolStripDropDownDirection direction) {
if (control == null) {
throw new ArgumentNullException("control");
}
SourceControlInternal = control;
this.displayLocation = CalculateDropDownLocation(control.PointToScreen(position), direction).Location;
this.Location = this.displayLocation;
ShowCore();
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.Show1"]/*' />
/// <devdoc> show relative to control coordinates </devdoc>
public void Show(Control control, int x, int y) {
if (control == null) {
throw new ArgumentNullException("control");
}
SourceControlInternal = control;
Show(control, new Point(x,y));
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.Show2"]/*' />
/// <devdoc> show relative to screen coordinates </devdoc>
public void Show(Point screenLocation) {
this.displayLocation = screenLocation;
this.Location = this.displayLocation;
ShowCore();
}
public void Show(Point position, ToolStripDropDownDirection direction) {
this.displayLocation = CalculateDropDownLocation(position, direction).Location;
this.Location = this.displayLocation;
ShowCore();
}
/// <include file='doc\ToolStripDropDown.uex' path='docs/doc[@for="ToolStripDropDown.Show3"]/*' />
/// <devdoc> show relative to screen coordinates </devdoc>
public void Show(int x, int y) {
this.displayLocation = new Point(x,y);
this.Location = this.displayLocation;
ShowCore();
}
private void ShowCore() {
Show();
}
private bool ShouldSerializeDropShadowEnabled() {
return dropShadowEnabled == false;
}
internal override bool ShouldSerializeLayoutStyle() {
return LayoutStyle != ToolStripLayoutStyle.VerticalStackWithOverflow;
}
internal void UnassignDropDownItem() {
Debug.Assert(countDropDownItemsAssignedTo > 0, "dropdown assignment underflow");
countDropDownItemsAssignedTo = Math.Max(--countDropDownItemsAssignedTo, 0);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m) {
if (m.Msg >= NativeMethods.WM_KEYFIRST && m.Msg <= NativeMethods.WM_KEYLAST && IsRestrictedWindow) {
// SECREVIEW:
// To Receive a OnKey* event, the ToolStripDropDown must have AllWindows permission
// directly calling DefWndProc will prevent these events from executing.
// All PreProcess keyboard messages are protected by link demands.
// NOTE the same kind of fix needs to go into ToolStripScrollButton.StickyLabel (the only alloewed ControlHost)
DefWndProc(ref m);
return;
}
switch (m.Msg) {
case NativeMethods.WM_NCACTIVATE:
// if someone clicks on a child control of the toolstrip dropdown, we want
// the title bar to continue appearing active. Normally we just show without
// taking window activation (ShowWindow(SHOWNOACTIVATE)) but we cant stop
// child controls from taking focus.
WmNCActivate(ref m);
return;
case NativeMethods.WM_ACTIVATE:
// This is the Chrome Panel collection editor scenario
// we had focus, then the Chrome panel was activated and we never went away
// when we get focus again, we should reactivate our message filter.
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.WndProc] got a WM_ACTIVATE " + (((int)m.WParam == NativeMethods.WA_ACTIVE) ? "WA_ACTIVE" : "WA_INACTIVE") + " - checkin if we need to set the active toolstrip");
if((int)m.WParam == NativeMethods.WA_ACTIVE) {
if (this.Visible) {
if (ToolStripManager.ModalMenuFilter.GetActiveToolStrip() != this) {
// if we were inactive and now we are, we should enter menu mode
ToolStripManager.ModalMenuFilter.SetActiveToolStrip(this);
}
}
else {
Debug.Fail("Why are we being activated when we're not visible? Deactivating thingee is " + WindowsFormsUtils.GetControlInformation(m.LParam));
}
}
else {
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown.WndProc] activating thingee is " + WindowsFormsUtils.GetControlInformation(m.LParam));
}
base.WndProc(ref m);
return;
/* case NativeMethods.WM_SYSKEYUP:
Keys keyData = (Keys)(int)m.WParam;
base.WndProc(ref m);
// VSW 423760: handle the case where the ALT key has been pressed down while a dropdown
// was open. We need to clear off the MenuKeyToggle so the next ALT will activate
// the menu.
if (IsMenuKey(keyData)) {
ToolStrip toplevel = GetToplevelOwnerToolStrip();
if (toplevel != null && toplevel.MenuKeyToggle) {
Debug.WriteLineIf(ToolStrip.SnapFocusDebug.TraceVerbose, "[ToolStripDropDown WM_SYSKEYUP]: Got Menu Key, restoring MenuKeyToggle.");
toplevel.MenuKeyToggle = false;
}
}
return;*/
default:
base.WndProc(ref m);
return;
}
}
#region DropDownSpecific
internal void DismissAll() {
ToolStripDropDown toplevel = this.GetFirstDropDown();
toplevel.closeReason = this.closeReason;
toplevel.DismissActiveDropDowns();
if (!LocalAppContextSwitches.UseLegacyContextMenuStripSourceControlValue) {
toplevel.saveSourceControl = this.saveSourceControl;
}
toplevel.Visible = false;
}
private void DismissActiveDropDowns() {
Debug.WriteLineIf((DropDownActivateDebug.TraceVerbose && ActiveDropDowns.Count > 0), "Dismiss children called - COUNT " + ActiveDropDowns.Count + " \r\n" + new StackTrace().ToString());
int count = ActiveDropDowns.Count;
if (count == 1) {
// this is the most common case
ToolStripDropDown dropDown = ActiveDropDowns[0] as ToolStripDropDown;
if (dropDown != null) {
dropDown.Visible = false;
}
}
else {
ArrayList dropDowns = ActiveDropDowns.Clone() as ArrayList;
// We cant iterate through the active dropdown collection
// here as changing visibility changes the collection.
for (int i = 0; i < dropDowns.Count; i++) {
ToolStripDropDown dropDown = dropDowns[i] as ToolStripDropDown;
if (dropDown != null) {
dropDown.Visible = false;
}
}
}
}
#region WMNCACTIVATE
private bool sendingActivateMessage = false;
// WmNcActivate
// if someone clicks on a child control of the toolstrip dropdown, we want
// the title bar to continue appearing active. Normally we just show without
// taking window activation (ShowWindow(SHOWNOACTIVATE)) but we cant stop
// child controls from taking focus.
private void WmNCActivate(ref Message m) {
if (m.WParam != IntPtr.Zero /*activating*/) {
if (!sendingActivateMessage) {
sendingActivateMessage = true;
try {
Debug.WriteLineIf(DropDownActivateDebug.TraceVerbose, "Sending WM_NCACTIVATE to toplevel hwnd" + ToolStripManager.ModalMenuFilter.ActiveHwnd);
// we're activating - notify the previous guy that we're activating.
HandleRef activeHwndHandleRef = ToolStripManager.ModalMenuFilter.ActiveHwnd;
UnsafeNativeMethods.SendMessage(activeHwndHandleRef, NativeMethods.WM_NCACTIVATE, (IntPtr)1, NativeMethods.InvalidIntPtr);
SafeNativeMethods.RedrawWindow(activeHwndHandleRef, null, NativeMethods.NullHandleRef, NativeMethods.RDW_FRAME | NativeMethods.RDW_INVALIDATE);
m.WParam = (IntPtr)1;
}
finally {
sendingActivateMessage = false;
}
}
DefWndProc(ref m);
return;
}
else {
base.WndProc(ref m);
}
}
#endregion
/// <devdoc>
/// Determines if this is the first dropDown in the dropDown chain
/// </devdoc>
internal bool IsFirstDropDown {
get {
return ((OwnerToolStrip as ToolStripDropDown) == null);
}
}
/// <devdoc>
/// returns the root dropdown in the chain.
/// </devdoc>
internal ToolStripDropDown GetFirstDropDown() {
ToolStripDropDown topmost = this;
// walk back up the chain of windows to get the topmost
ToolStripDropDown ownerDropDown = topmost.OwnerToolStrip as ToolStripDropDown;
while (ownerDropDown != null) {
topmost = ownerDropDown;
ownerDropDown = topmost.OwnerToolStrip as ToolStripDropDown;
}
return topmost;
}
internal static ToolStripDropDown GetFirstDropDown(ToolStrip start) {
Debug.Assert(start != null, "Who is passing null to GetFirstDropDown?");
if ((start == null) || (!start.IsDropDown)) {
return null;
}
ToolStripDropDown startDropDown = (start as ToolStripDropDown);
return startDropDown.GetFirstDropDown();
}
#endregion DropDownSpecific
/// <include file='doc\ToolStrip.uex' path='docs/doc[@for="ToolStripAccessibleObject"]/*' />
[System.Runtime.InteropServices.ComVisible(true)]
public class ToolStripDropDownAccessibleObject : ToolStripAccessibleObject {
private ToolStripDropDown owner;
/// <include file='doc\ToolStrip.uex' path='docs/doc[@for="ToolStripAccessibleObject.ToolStripAccessibleObject"]/*' />
public ToolStripDropDownAccessibleObject(ToolStripDropDown owner) : base(owner) {
this.owner = owner;
}
public override string Name {
get {
// Special case: If an explicit name has been set in the AccessibleName property, use that.
// Note: Any non-null value in AccessibleName overrides the default accessible name logic,
// even an empty string (this is the only way to *force* the accessible name to be blank).
string name = owner.AccessibleName;
if (name != null) {
return name;
}
// NOT localized for testing purposes. Localizers can use AccessibleName.
name = "DropDown";
if (owner.OwnerItem != null && owner.OwnerItem.AccessibilityObject.Name != null) {
name = owner.OwnerItem.AccessibilityObject.Name + name;
}
return name;
}
set {
// If anyone tries to set the accessible name, just cache the value in the control's
// AccessibleName property. This value will then end up overriding the normal accessible
// name logic, until such time as AccessibleName is set back to null.
owner.AccessibleName = value;
}
}
public override AccessibleRole Role {
get {
AccessibleRole role = Owner.AccessibleRole;
if (role != AccessibleRole.Default) {
return role;
}
return AccessibleRole.MenuPopup;
}
}
}
}
}
|