| File: System\Windows\Forms\Controls\Menus\MenuStrip.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// 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 Windows.Win32.UI.Accessibility; namespace System.Windows.Forms; [SRDescription(nameof(SR.DescriptionMenuStrip))] public partial class MenuStrip : ToolStrip { private ToolStripMenuItem? _mdiWindowListItem; private static readonly object s_menuActivateEvent = new(); private static readonly object s_menuDeactivateEvent = new(); public MenuStrip() { CanOverflow = false; GripStyle = ToolStripGripStyle.Hidden; Stretch = true; } internal override bool KeyboardActive { get => base.KeyboardActive; set { if (base.KeyboardActive != value) { base.KeyboardActive = value; if (value) { OnMenuActivate(EventArgs.Empty); } else { OnMenuDeactivate(EventArgs.Empty); } } } } [DefaultValue(false)] [SRDescription(nameof(SR.ToolStripCanOverflowDescr))] [SRCategory(nameof(SR.CatLayout))] [Browsable(false)] public new bool CanOverflow { get => base.CanOverflow; set => base.CanOverflow = value; } protected override bool DefaultShowItemToolTips => false; protected override Padding DefaultGripMargin => // MenuStrip control is scaled by Control::ScaleControl() // Ensure grip aligns properly when set visible. ScaleHelper.IsThreadPerMonitorV2Aware ? ScaleHelper.ScaleToDpi(new Padding(2, 2, 0, 2), DeviceDpi) : new Padding(2, 2, 0, 2); protected override Size DefaultSize => ScaleHelper.IsThreadPerMonitorV2Aware ? ScaleHelper.ScaleToDpi(new Size(200, 24), DeviceDpi) : new Size(200, 24); protected override Padding DefaultPadding { get { // MenuStrip control is scaled by Control::ScaleControl() // Scoot the grip over when present return GripStyle == ToolStripGripStyle.Visible ? ScaleHelper.IsThreadPerMonitorV2Aware ? ScaleHelper.ScaleToDpi(new Padding(3, 2, 0, 2), DeviceDpi) : new Padding(3, 2, 0, 2) : ScaleHelper.IsThreadPerMonitorV2Aware ? ScaleHelper.ScaleToDpi(new Padding(6, 2, 0, 2), DeviceDpi) : new Padding(6, 2, 0, 2); } } [DefaultValue(ToolStripGripStyle.Hidden)] public new ToolStripGripStyle GripStyle { get => base.GripStyle; set => base.GripStyle = value; } [SRCategory(nameof(SR.CatBehavior))] [SRDescription(nameof(SR.MenuStripMenuActivateDescr))] public event EventHandler? MenuActivate { add => Events.AddHandler(s_menuActivateEvent, value); remove => Events.RemoveHandler(s_menuActivateEvent, value); } [SRCategory(nameof(SR.CatBehavior))] [SRDescription(nameof(SR.MenuStripMenuDeactivateDescr))] public event EventHandler? MenuDeactivate { add => Events.AddHandler(s_menuDeactivateEvent, value); remove => Events.RemoveHandler(s_menuDeactivateEvent, value); } [DefaultValue(false)] [SRDescription(nameof(SR.ToolStripShowItemToolTipsDescr))] [SRCategory(nameof(SR.CatBehavior))] public new bool ShowItemToolTips { get => base.ShowItemToolTips; set => base.ShowItemToolTips = value; } [DefaultValue(true)] [SRCategory(nameof(SR.CatLayout))] [SRDescription(nameof(SR.ToolStripStretchDescr))] public new bool Stretch { get => base.Stretch; set => base.Stretch = value; } [DefaultValue(null)] [MergableProperty(false)] [SRDescription(nameof(SR.MenuStripMdiWindowListItem))] [SRCategory(nameof(SR.CatBehavior))] [TypeConverter(typeof(MdiWindowListItemConverter))] public ToolStripMenuItem? MdiWindowListItem { get => _mdiWindowListItem; set => _mdiWindowListItem = value; } protected override AccessibleObject CreateAccessibilityInstance() => new MenuStripAccessibleObject(this); protected internal override ToolStripItem CreateDefaultItem(string? text, Image? image, EventHandler? onClick) { if (text == "-") { return new ToolStripSeparator(); } else { return new ToolStripMenuItem(text, image, onClick); } } internal override ToolStripItem? GetNextItem(ToolStripItem? start, ArrowDirection direction, bool rtlAware) { ToolStripItem? nextItem = base.GetNextItem(start, direction, rtlAware); if (nextItem is MdiControlStrip.SystemMenuItem) { nextItem = base.GetNextItem(nextItem, direction, rtlAware); } return nextItem; } protected virtual void OnMenuActivate(EventArgs e) { if (IsHandleCreated) { if (!TabStop && !DesignMode && IsAccessibilityObjectCreated) { AccessibilityObject.RaiseAutomationEvent(UIA_EVENT_ID.UIA_MenuModeStartEventId); AccessibilityObject.RaiseAutomationEvent(UIA_EVENT_ID.UIA_MenuOpenedEventId); } AccessibilityNotifyClients(AccessibleEvents.SystemMenuStart, (int)OBJECT_IDENTIFIER.OBJID_MENU, -1); } ((EventHandler?)Events[s_menuActivateEvent])?.Invoke(this, e); } protected virtual void OnMenuDeactivate(EventArgs e) { if (IsHandleCreated) { AccessibilityNotifyClients(AccessibleEvents.SystemMenuEnd, (int)OBJECT_IDENTIFIER.OBJID_MENU, -1); if (!TabStop && !DesignMode && IsAccessibilityObjectCreated) { AccessibilityObject.RaiseAutomationEvent(UIA_EVENT_ID.UIA_MenuClosedEventId); AccessibilityObject.RaiseAutomationEvent(UIA_EVENT_ID.UIA_MenuModeEndEventId); } } ((EventHandler?)Events[s_menuDeactivateEvent])?.Invoke(this, e); } /// <summary> /// Called from ToolStripManager.ProcessMenuKey. Fires MenuActivate event and sets focus. /// </summary> internal bool OnMenuKey() { if (!(Focused || ContainsFocus)) { ToolStripManager.ModalMenuFilter.SetActiveToolStrip(this, menuKeyPressed: true); if (DisplayedItems.Count > 0) { if (DisplayedItems[0] is MdiControlStrip.SystemMenuItem) { SelectNextToolStripItem(DisplayedItems[0], forward: true); } else { // first alt should select "File". Future keydowns of alt should restore focus. SelectNextToolStripItem(null, forward: RightToLeft == RightToLeft.No); } } return true; } return false; } protected override bool ProcessCmdKey(ref Message m, Keys keyData) { if (ToolStripManager.ModalMenuFilter.InMenuMode) { // ALT, then space should dismiss the menu and activate the system menu. if (keyData == Keys.Space) { // If we're focused it's ok to activate system menu. If we're not focused - we should not activate if // we contain focus - this means a text box or something has focus. if (Focused || !ContainsFocus) { NotifySelectionChange(item: null); ToolStripManager.ModalMenuFilter.ExitMenuMode(); // Send a WM_SYSCOMMAND SC_KEYMENU + Space to activate the system menu. HWND ancestor = PInvoke.GetAncestor(this, GET_ANCESTOR_FLAGS.GA_ROOT); PInvokeCore.PostMessage(ancestor, PInvokeCore.WM_SYSCOMMAND, (WPARAM)PInvoke.SC_KEYMENU, (LPARAM)(int)Keys.Space); return true; } } } return base.ProcessCmdKey(ref m, keyData); } protected override void WndProc(ref Message m) { if (m.Msg == (int)PInvokeCore.WM_MOUSEACTIVATE && (ActiveDropDowns.Count == 0)) { // call menu activate before we actually take focus. Point pt = PointToClient(WindowsFormsUtils.LastCursorPoint); ToolStripItem? item = GetItemAt(pt); if (item is not null && !(item is ToolStripControlHost)) { // verify the place where we've clicked is a place where we have to do "fake" focus // e.g. an item that isn't a control. KeyboardActive = true; } } base.WndProc(ref m); } }