2007-04-26 Jonathan Pobst <monkey@jpobst.com>
authorJonathan Pobst <monkey@jpobst.com>
Thu, 26 Apr 2007 20:25:18 +0000 (20:25 -0000)
committerJonathan Pobst <monkey@jpobst.com>
Thu, 26 Apr 2007 20:25:18 +0000 (20:25 -0000)
* Application.cs: Create a shortcut path so that currently selected
MenuStrips can intercept keyboard events without having focus.
* Control.cs: Handle WM_SYSCOMMAND message to activate MenuStrips.
* MenuStrip.cs, ToolStrip.cs, ToolStripDropDown.cs, ToolStripDropDownItem.cs,
ToolStripItem.cs, ToolStripManager.cs, ToolStripMenuItem.cs: Support
keyboard navigation (arrows, tab, enter, esc) on Windows.  Still need to
generate WM_SYSCOMMAND message in X11 for other platforms.
* ToolStripProfessionalRenderer.cs: ToolStripMenuItems need to be painted
in OnRenderMenuItemBackground instead of OnRenderButtonBackground.
* ToolStripSplitButton.cs: Add DefaultItem property.

svn path=/trunk/mcs/; revision=76353

12 files changed:
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/MenuStrip.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStrip.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripDropDown.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripDropDownItem.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripItem.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripManager.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripMenuItem.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripProfessionalRenderer.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolStripSplitButton.cs

index 1f829e66fb396f0e1ae8a151105e367b9d15e1bf..614eb74f761eed0fbf27e498a172c8c8f87c6643 100644 (file)
@@ -142,6 +142,7 @@ namespace System.Windows.Forms {
                private static bool                     use_wait_cursor         = false;
 
 #if NET_2_0
+               private static ToolStrip keyboard_capture;
                private static VisualStyleState visual_style_state = VisualStyleState.ClientAndNonClientAreasEnabled;
 #endif
 
@@ -659,9 +660,20 @@ namespace System.Windows.Forms {
                                case Msg.WM_KEYUP:
                                case Msg.WM_SYSKEYUP:
                                        Message m;
+                                       m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);
+
+#if NET_2_0
+                                       // If we have a control with keyboard capture (usually a *Strip)
+                                       // give it the message, and then drop the message
+                                       if (keyboard_capture != null) {
+                                               m.HWnd = keyboard_capture.Handle;
+                                               keyboard_capture.PreProcessMessage (ref m);
+                                               continue;
+                                       }
+#endif
+
                                        Control c;
 
-                                       m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);
                                        c = Control.FromHandle(msg.hwnd);
                                        if ((c != null) && !c.PreProcessMessage(ref m)) {
                                                goto default;
@@ -750,6 +762,15 @@ namespace System.Windows.Forms {
 #endif
                #endregion      // Events
 
+               #region Internal Properties
+#if NET_2_0
+               internal static ToolStrip KeyboardCapture {
+                       get { return keyboard_capture; }
+                       set { keyboard_capture = value; }
+               }
+#endif
+               #endregion
+               
                #region Internal Methods
                internal static void AddForm (Form f)
                {
index e0bb5904a73b206e8a676965db02370a5cd10bc0..b562975f52a00eac57a7e89a84278ce26f32b2f2 100644 (file)
@@ -1,3 +1,16 @@
+2007-04-26  Jonathan Pobst  <monkey@jpobst.com>
+
+       * Application.cs: Create a shortcut path so that currently selected
+       MenuStrips can intercept keyboard events without having focus.
+       * Control.cs: Handle WM_SYSCOMMAND message to activate MenuStrips.
+       * MenuStrip.cs, ToolStrip.cs, ToolStripDropDown.cs, ToolStripDropDownItem.cs,
+       ToolStripItem.cs, ToolStripManager.cs, ToolStripMenuItem.cs: Support
+       keyboard navigation (arrows, tab, enter, esc) on Windows.  Still need to
+       generate WM_SYSCOMMAND message in X11 for other platforms.
+       * ToolStripProfessionalRenderer.cs: ToolStripMenuItems need to be painted
+       in OnRenderMenuItemBackground instead of OnRenderButtonBackground.
+       * ToolStripSplitButton.cs: Add DefaultItem property.
+       
 2007-04-26  Everaldo Canuto  <everaldo@simios.org>
 
        * MainMenu.cs: In OnMenuChanged pass PaintEventArgs to Draw method, it
index 77888ae5e06919025e9160372f987d381d203407..d1858d2b79e82e39f13114137732d15804f09479 100644 (file)
@@ -4751,11 +4751,20 @@ namespace System.Windows.Forms
                                        return;
                                }
 
+#if NET_2_0
+                               // The menu button was pressed (the Alt key)
+                               case Msg.WM_SYSCOMMAND: {
+                                       WmSysCommand (ref m);
+                                       return;
+                               }
+#endif
+                       
                                default:
                                        DefWndProc(ref m);
                                        return;
                        }
                }
+
                #endregion      // Public Instance Methods
 
                #region WM methods
@@ -5135,6 +5144,16 @@ namespace System.Windows.Forms
                        OnSystemColorsChanged(EventArgs.Empty);
                }
 
+#if NET_2_0
+               private void WmSysCommand (ref Message m)
+               {
+                       if (m.WParam == (IntPtr)61696)  // SC_KEYMENU (Alt)
+                               ToolStripManager.ProcessMenuKey (ref m);
+                       else
+                               DefWndProc (ref m);
+               }
+#endif
+
                private void WmSetCursor (ref Message m) {
                        if ((cursor == null) || ((HitTest)(m.LParam.ToInt32() & 0xffff) != HitTest.HTCLIENT)) {
                                DefWndProc(ref m);
index aedcf17c3ba14d68a7300af4282be23bbd91a5f4..79354cbcc74569c4c56e8811b108ca854171317b 100644 (file)
@@ -139,8 +139,37 @@ namespace System.Windows.Forms
                        remove { Events.RemoveHandler (MenuDeactivateEvent, value); }
                }
                #endregion
+
+               #region Internal Properties
+               internal override bool KeyboardActive {
+                       get { return base.KeyboardActive; }
+                       set {
+                               if (base.KeyboardActive != value) {
+                                       base.KeyboardActive = value;
+                                       
+                                       if (value)
+                                               this.OnMenuActivate (EventArgs.Empty);
+                                       else
+                                               this.OnMenuDeactivate (EventArgs.Empty);
+                               }
+                       }
+               }
+               
+               internal bool MenuDroppedDown {
+                       get { return this.menu_selected; }
+                       set { this.menu_selected = value; }
+               }
+               #endregion
                
                #region Internal Methods
+               internal override void Dismiss (ToolStripDropDownCloseReason reason)
+               {
+                       // Make sure we don't auto-dropdown next time we're activated
+                       this.MenuDroppedDown = false;
+                       
+                       base.Dismiss (reason);
+               }
+               
                internal void FireMenuActivate ()
                {
                        // The tracker lets us know when the form is clicked or loses focus
@@ -159,14 +188,22 @@ namespace System.Windows.Forms
                        this.OnMenuDeactivate (EventArgs.Empty);
                }
 
+               internal override bool OnMenuKey ()
+               {
+                       // Set ourselves active and select our first item
+                       ToolStripManager.SetActiveToolStrip (this);
+                       this.SelectNextToolStripItem (null, true);
+                       return true;
+               }
+               
                private void ToolStripMenuTracker_AppFocusChange (object sender, EventArgs e)
                {
-                       this.HideMenus (true, ToolStripDropDownCloseReason.AppFocusChange);
+                       this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
                }
 
                private void ToolStripMenuTracker_AppClicked (object sender, EventArgs e)
                {
-                       this.HideMenus (true, ToolStripDropDownCloseReason.AppClicked);
+                       this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppClicked);
                }
                
                internal void RefreshMdiItems ()
index d5916b18d25c7055474f6834b724ab5110c6dc34..277a299154f043579e023248e222050498d15643 100644 (file)
@@ -57,6 +57,7 @@ namespace System.Windows.Forms
                private Size image_scaling_size;
                private bool is_currently_merged;
                private ToolStripItemCollection items;
+               private bool keyboard_active;
                private LayoutEngine layout_engine;
                private LayoutSettings layout_settings;
                private ToolStripLayoutStyle layout_style;
@@ -71,7 +72,7 @@ namespace System.Windows.Forms
                private bool stretch;
 
                private ToolStripItem mouse_currently_over;
-               private bool menu_selected;
+               internal bool menu_selected;
                private ToolStripItem tooltip_currently_showing;
                #endregion
 
@@ -515,9 +516,6 @@ namespace System.Windows.Forms
                        if (!Enum.IsDefined (typeof (ArrowDirection), direction))
                                throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ArrowDirection", direction));
 
-                       if (this.Items.Count == 1)
-                               return null;
-                               
                        ToolStripItem current_best = null;
                        int current_best_point;
                        
@@ -671,6 +669,16 @@ namespace System.Windows.Forms
                        base.OnDockChanged (e);
                }
 
+               protected override bool IsInputChar (char charCode)
+               {
+                       return base.IsInputChar (charCode);
+               }
+
+               protected override bool IsInputKey (Keys keyData)
+               {
+                       return base.IsInputKey (keyData);
+               }
+               
                protected override void OnEnabledChanged (EventArgs e)
                {
                        base.OnEnabledChanged (e);
@@ -713,6 +721,8 @@ namespace System.Windows.Forms
 
                protected virtual void OnItemClicked (ToolStripItemClickedEventArgs e)
                {
+                       ToolStripManager.SetActiveToolStrip (null);
+                       
                        ToolStripItemClickedEventHandler eh = (ToolStripItemClickedEventHandler)(Events [ItemClickedEvent]);
                        if (eh != null)
                                eh (this, e);
@@ -969,8 +979,38 @@ namespace System.Windows.Forms
 
                protected override bool ProcessCmdKey (ref Message msg, Keys keyData)
                {
+                       if ((keyData & Keys.Alt) == Keys.Alt && this.KeyboardActive) {
+                               this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.Keyboard);
+                               return true;
+                       }
+                       
                        return base.ProcessCmdKey (ref msg, keyData);
                }
+
+               protected override bool ProcessDialogKey (Keys keyData)
+               {
+                       // Give each item a chance to handle the key
+                       foreach (ToolStripItem tsi in this.Items)
+                               if (tsi.ProcessDialogKey (keyData))
+                                       return true;
+                       
+                       // See if I want to handle it
+                       if (this.ProcessArrowKey (keyData))
+                               return true;
+                       
+                       switch (keyData) {
+                               case Keys.Escape:
+                                       this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
+                                       return true;
+                       }
+
+                       return base.ProcessDialogKey (keyData);
+               }
+
+               protected override bool ProcessMnemonic (char charCode)
+               {
+                       return base.ProcessMnemonic (charCode);
+               }
                
                protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
                {
@@ -1110,7 +1150,57 @@ namespace System.Windows.Forms
                }
                #endregion
 
+               #region Internal Properties
+               internal virtual bool KeyboardActive
+               {
+                       get { return this.keyboard_active; }
+                       set {
+                               if (this.keyboard_active != value) {
+                                       this.keyboard_active = value;
+                                       
+                                       if (value)
+                                               Application.KeyboardCapture = this;
+                                       else if (Application.KeyboardCapture == this)
+                                               Application.KeyboardCapture = null;
+                               }
+                       }
+               }
+               #endregion
+               
                #region Private Methods
+               internal void ChangeSelection (ToolStripItem nextItem)
+               {
+                       if (Application.KeyboardCapture != this)
+                               ToolStripManager.SetActiveToolStrip (this);
+                               
+                       foreach (ToolStripItem tsi in this.Items)
+                               if (tsi != nextItem)
+                                       tsi.Dismiss (ToolStripDropDownCloseReason.Keyboard);
+                                       
+                       nextItem.Select ();
+                       
+                       if (nextItem.Parent is MenuStrip && (nextItem.Parent as MenuStrip).MenuDroppedDown)
+                               (nextItem as ToolStripMenuItem).HandleAutoExpansion ();
+               }
+               
+               internal virtual void Dismiss ()
+               {
+                       this.Dismiss (ToolStripDropDownCloseReason.AppClicked);
+               }
+               
+               internal virtual void Dismiss (ToolStripDropDownCloseReason reason)
+               {
+                       // Release our stranglehold on the keyboard
+                       this.KeyboardActive = false;
+                       
+                       // Set our drop down flag to false;
+                       this.menu_selected = false;
+                       
+                       // Make sure all of our items are deselected and repainted
+                       foreach (ToolStripItem tsi in this.Items)
+                               tsi.Dismiss (reason);
+               }
+               
                private void DoAutoSize ()
                {
                        if (this.AutoSize == true && this.Dock == DockStyle.None)
@@ -1120,6 +1210,15 @@ namespace System.Windows.Forms
                                this.Height = GetPreferredSize (Size.Empty).Height;
                }
 
+               internal ToolStripItem GetCurrentlySelectedItem ()
+               {
+                       foreach (ToolStripItem tsi in this.DisplayedItems)
+                               if (tsi.Selected)
+                                       return tsi;
+                                       
+                       return null;
+               }
+               
                public override Size GetPreferredSize (Size proposedSize)
                {
                        Size new_size = new Size (0, this.Height);
@@ -1146,6 +1245,17 @@ namespace System.Windows.Forms
                        return new_size;
                }
                
+               internal virtual ToolStrip GetTopLevelToolStrip ()
+               {
+                       return this;
+               }
+               
+               internal void HandleItemClick (ToolStripItem dismissingItem)
+               {
+                       this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
+                       this.OnItemClicked (new ToolStripItemClickedEventArgs (dismissingItem));
+               }
+               
                internal void HideMenus (bool release, ToolStripDropDownCloseReason reason)
                {
                        if (this is MenuStrip && release && menu_selected)
@@ -1174,8 +1284,41 @@ namespace System.Windows.Forms
                        
                                this.OverflowButton.HideDropDown ();
                        }
+                       
+                       foreach (ToolStripItem tsi2 in this.Items)
+                               if (tsi != tsi2)
+                                       tsi2.Dismiss (ToolStripDropDownCloseReason.Keyboard);
                }
                
+               internal virtual bool OnMenuKey ()
+               {
+                       return false;
+               }
+
+               internal virtual bool ProcessArrowKey (Keys keyData)
+               {
+                       switch (keyData) {
+                               case Keys.Right:
+                               case Keys.Tab:
+                                       this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), true);
+                                       return true;
+                               case Keys.Left:
+                               case Keys.Shift | Keys.Tab:
+                                       this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), false);
+                                       return true;
+                       }
+
+                       return false;
+               }
+
+               internal virtual void SelectNextToolStripItem (ToolStripItem start, bool forward)
+               {
+                       ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Right : ArrowDirection.Left);
+                       
+                       this.ChangeSelection (next_item);
+               }
+
+               #region Stuff for ToolTips
                private void MouseEnteredItem (ToolStripItem item)
                {
                        if (this.show_item_tool_tips) {
@@ -1224,7 +1367,9 @@ namespace System.Windows.Forms
 
                        ToolTipTimer.Stop ();
                }
-               
+               #endregion
+
+               #region Stuff for Merging
                internal ToolStrip CurrentlyMergedWith {
                        get { return this.currently_merged_with; }
                        set { this.currently_merged_with = value; }
@@ -1300,6 +1445,7 @@ namespace System.Windows.Forms
                        item.Owner.Items.AddNoOwnerOrLayout (item);
                }
                #endregion
+               #endregion
        }
 }
 #endif
index 8cbd2432d7a22feaa87ffb1549147ea51a395d57..a490b9a358bc6150e1c4aeee0670aa409c9f2d34 100644 (file)
@@ -319,6 +319,9 @@ namespace System.Windows.Forms
 
                public void Close (ToolStripDropDownCloseReason reason)
                {
+                       if (!this.Visible)
+                               return;
+                               
                        // Give users a chance to cancel the close
                        ToolStripDropDownClosingEventArgs e = new ToolStripDropDownClosingEventArgs (reason);
                        this.OnClosing (e);
@@ -343,8 +346,7 @@ namespace System.Windows.Forms
 
                        // Recursive hide all child dropdowns
                        foreach (ToolStripItem tsi in this.Items)
-                               if (tsi is ToolStripMenuItem)
-                                       (tsi as ToolStripMenuItem).HideDropDown (reason);
+                               tsi.Dismiss (reason);
                        
                        this.OnClosed (new ToolStripDropDownClosedEventArgs (reason));
                }
@@ -365,6 +367,8 @@ namespace System.Windows.Forms
 
                        base.Show ();
                        
+                       ToolStripManager.SetActiveToolStrip (this);
+                       
                        this.OnOpened (EventArgs.Empty);
                }
                
@@ -797,19 +801,93 @@ namespace System.Windows.Forms
                #endregion
 
                #region Private Methods
+               internal override void Dismiss (ToolStripDropDownCloseReason reason)
+               {
+                       this.Close (reason);
+                       base.Dismiss (reason);
+               }
+
+               internal override ToolStrip GetTopLevelToolStrip ()
+               {
+                       if (this.OwnerItem == null)
+                               return this;
+                               
+                       return this.OwnerItem.GetTopLevelToolStrip ();
+               }
+
+               internal override bool ProcessArrowKey (Keys keyData)
+               {
+                       switch (keyData) {
+                               case Keys.Down:
+                               case Keys.Tab:
+                                       this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), true);
+                                       return true;
+                               case Keys.Up:
+                               case Keys.Shift | Keys.Tab:
+                                       this.SelectNextToolStripItem (this.GetCurrentlySelectedItem (), false);
+                                       return true;
+                               case Keys.Right:
+                                       this.GetTopLevelToolStrip ().SelectNextToolStripItem (this.TopLevelOwnerItem, true);
+                                       return true;
+                               case Keys.Left:
+                               case Keys.Escape:
+                                       this.Dismiss (ToolStripDropDownCloseReason.Keyboard);
+                                       
+                                       ToolStrip parent_strip = this.OwnerItem.Parent;
+                                       ToolStripManager.SetActiveToolStrip (parent_strip);
+                                       
+                                       if (parent_strip is MenuStrip && keyData == Keys.Left) {
+                                               parent_strip.SelectNextToolStripItem (this.TopLevelOwnerItem, false);
+                                               this.TopLevelOwnerItem.Invalidate ();
+                                       } else if (parent_strip is MenuStrip && keyData == Keys.Escape) {
+                                               (parent_strip as MenuStrip).MenuDroppedDown = false;
+                                               this.TopLevelOwnerItem.Select ();
+                                       }                               
+                                       return true;
+                       }
+                       
+                       return false;
+               }
+
+               internal override void SelectNextToolStripItem (ToolStripItem start, bool forward)
+               {
+                       ToolStripItem next_item = this.GetNextItem (start, forward ? ArrowDirection.Down : ArrowDirection.Up);
+
+                       if (next_item != null)
+                               this.ChangeSelection (next_item);
+               }
+               
                private void ToolStripMenuTracker_AppFocusChange (object sender, EventArgs e)
                {
-                       this.Close (ToolStripDropDownCloseReason.AppFocusChange);
+                       this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
                }
 
                private void ToolStripMenuTracker_AppClicked (object sender, EventArgs e)
                {
-                       this.Close (ToolStripDropDownCloseReason.AppClicked);
+                       this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.AppClicked);
                }
                #endregion
 
                #region Internal Properties
                internal override bool ActivateOnShow { get { return false; } }
+               
+               internal ToolStripItem TopLevelOwnerItem {
+                       get {
+                               ToolStripItem owner_item = this.OwnerItem;
+                               ToolStrip ts = null;
+
+                               while (owner_item != null) {
+                                       ts = owner_item.Owner;
+
+                                       if (ts != null && (ts is ToolStripDropDown))
+                                               owner_item = (ts as ToolStripDropDown).OwnerItem;
+                                       else
+                                               return owner_item;
+                               }
+
+                               return null;
+                       }
+               }
                #endregion
        }
 }
index 1c8a85676c169efd09fbfe1566234f7022c2cea3..8e3df6c01f5e79996a56a7280daeb88812794a9f 100644 (file)
@@ -138,7 +138,8 @@ namespace System.Windows.Forms
                {
                        if (!this.HasDropDownItems)
                                return;
-                               
+                       
+                       this.Invalidate ();
                        this.OnDropDownOpening (this, EventArgs.Empty);
                        this.DropDown.Show (this.DropDownLocation);
                        this.OnDropDownShow (EventArgs.Empty);
@@ -213,6 +214,43 @@ namespace System.Windows.Forms
 
                        return base.ProcessCmdKey (ref m, keyData);
                }
+
+               protected internal override bool ProcessDialogKey (Keys keyData)
+               {
+                       if (!this.Selected || !this.HasDropDownItems)
+                               return base.ProcessDialogKey (keyData);
+                               
+                       if (!this.IsOnDropDown) {
+                               if (this.Parent.Orientation == Orientation.Horizontal) {
+                                       if (keyData == Keys.Down || keyData == Keys.Enter) {
+                                               if (this.Parent is MenuStrip)
+                                                       (this.Parent as MenuStrip).MenuDroppedDown = true;
+                                               this.ShowDropDown ();
+                                               this.DropDown.SelectNextToolStripItem (null, true);
+                                               return true;
+                                       }
+                               } else {
+                                       if (keyData == Keys.Right || keyData == Keys.Enter) {
+                                               if (this.Parent is MenuStrip)
+                                                       (this.Parent as MenuStrip).MenuDroppedDown = true;
+                                               this.ShowDropDown ();
+                                               this.DropDown.SelectNextToolStripItem (null, true);
+                                               return true;
+                                       }
+                               }
+                       } else {
+                               if (keyData == Keys.Right || keyData == Keys.Enter) {
+                                       if (this.HasDropDownItems) {
+                                               this.ShowDropDown ();
+                                               this.DropDown.SelectNextToolStripItem (null, true);
+                                               return true;
+                                       }
+                               }
+                       }
+                       
+                       
+                       return base.ProcessDialogKey (keyData);
+               }
                #endregion
 
                #region Public Events
@@ -243,6 +281,14 @@ namespace System.Windows.Forms
                #endregion
 
                #region Internal Methods
+               internal override void Dismiss (ToolStripDropDownCloseReason reason)
+               {
+                       if (this.HasDropDownItems && this.DropDown.Visible)
+                               this.DropDown.Dismiss (reason);
+                               
+                       base.Dismiss (reason);
+               }
+               
                internal void HideDropDown (ToolStripDropDownCloseReason reason)
                {
                        if (this.drop_down == null || !this.DropDown.Visible)
index 982cefd8e683fadf0d00a2c7f69927b0d22baac9..2e1bfe8b842fc3c9c531e5ca5e0948669c856ac6 100644 (file)
@@ -853,6 +853,16 @@ namespace System.Windows.Forms
                        base.Dispose (disposing);
                }
                
+               protected internal virtual bool IsInputChar (char charCode)
+               {
+                       return false;
+               }
+               
+               protected internal virtual bool IsInputKey (Keys keyData)
+               {
+                       return false;
+               }
+               
                protected virtual void OnAvailableChanged (EventArgs e)
                {
                        EventHandler eh = (EventHandler)(Events [AvailableChangedEvent]);
@@ -870,7 +880,7 @@ namespace System.Windows.Forms
 
                protected virtual void OnBoundsChanged ()
                {
-                       OnLayout (new LayoutEventArgs(null, ""));
+                       OnLayout (new LayoutEventArgs(null, string.Empty));
                }
 
                protected virtual void OnClick (EventArgs e)
@@ -1099,6 +1109,21 @@ namespace System.Windows.Forms
                        return false;
                }
                
+               protected internal virtual bool ProcessDialogKey (Keys keyData)
+               {
+                       if (this.Selected && keyData == Keys.Enter) {
+                               this.FireEvent (EventArgs.Empty, ToolStripItemEventType.Click);
+                               return true;
+                       }
+                               
+                       return false;
+               }
+               
+               protected internal virtual bool ProcessMnemonic (char charCode)
+               {
+                       return false;
+               }
+               
                protected internal virtual void SetBounds (Rectangle bounds)
                {
                        if (this.bounds != bounds) {
@@ -1404,6 +1429,22 @@ namespace System.Windows.Forms
                        }
                }
 
+               internal virtual void Dismiss (ToolStripDropDownCloseReason reason)
+               {
+                       if (is_selected) {
+                               this.is_selected = false;
+                               this.Invalidate ();
+                       }
+               }
+
+               internal virtual ToolStrip GetTopLevelToolStrip ()
+               {
+                       if (this.Parent != null)
+                               return this.Parent.GetTopLevelToolStrip ();
+                               
+                       return null;
+               }
+
                private void LayoutTextBeforeOrAfterImage (Rectangle totalArea, bool textFirst, Size textSize, Size imageSize, ContentAlignment textAlign, ContentAlignment imageAlign, out Rectangle textRect, out Rectangle imageRect)
                {
                        int element_spacing = 0;        // Spacing between the Text and the Image
@@ -1489,7 +1530,7 @@ namespace System.Windows.Forms
                        switch (met) {
                                case ToolStripItemEventType.MouseUp:
                                        this.OnMouseUp ((MouseEventArgs)e);
-                                       this.OnClick ((MouseEventArgs)e);
+                                       this.HandleClick (e);
                                        break;
                                case ToolStripItemEventType.MouseDown:
                                        this.OnMouseDown ((MouseEventArgs)e);
@@ -1510,11 +1551,17 @@ namespace System.Windows.Forms
                                        this.OnPaint ((PaintEventArgs)e);
                                        break;
                                case ToolStripItemEventType.Click:
-                                       this.OnClick (e);
+                                       this.HandleClick (e);
                                        break;
                        }
                }
                
+               internal virtual void HandleClick (EventArgs e)
+               {
+                       this.Parent.HandleItemClick (this);
+                       this.OnClick (e);
+               }
+               
                internal virtual void SetPlacement (ToolStripItemPlacement placement)
                {
                        this.placement = placement;
index 60d0111de7746c2f47561b13a096b6bc41439d67..46f448f0e8cb69fd90f7f7c46c61f14f786a49e7 100644 (file)
@@ -36,22 +36,13 @@ namespace System.Windows.Forms
 {
        public sealed class ToolStripManager
        {
-               private static ToolStripRenderer renderer;
-               private static ToolStripManagerRenderMode render_mode;
-               private static bool visual_styles_enabled;
-               private static List<ToolStrip> toolstrips;
-               private static List<ToolStripMenuItem> menu_items;
+               private static ToolStripRenderer renderer = new ToolStripProfessionalRenderer ();
+               private static ToolStripManagerRenderMode render_mode = ToolStripManagerRenderMode.Professional;
+               private static bool visual_styles_enabled = Application.RenderWithVisualStyles;
+               private static List<ToolStrip> toolstrips = new List<ToolStrip> ();
+               private static List<ToolStripMenuItem> menu_items = new List<ToolStripMenuItem> ();
                
-               #region Static Constructor
-               static ToolStripManager ()
-               {
-                       toolstrips = new List<ToolStrip> ();
-                       menu_items = new List<ToolStripMenuItem> ();
-                       ToolStripManager.renderer = new ToolStripProfessionalRenderer ();
-                       ToolStripManager.render_mode = ToolStripManagerRenderMode.Professional;
-                       ToolStripManager.visual_styles_enabled = Application.RenderWithVisualStyles;
-               }
-
+               #region Private Constructor
                private ToolStripManager ()
                {
                }
@@ -407,6 +398,37 @@ namespace System.Windows.Forms
                                toolstrips.Add (ts);
                }
 
+               internal static ToolStrip GetNextToolStrip (ToolStrip ts, bool forward)
+               {
+                       lock (toolstrips) {
+                               int index = toolstrips.IndexOf (ts);
+                               
+                               if (forward) {
+                                       // Look for any toolstrip after this one in the collection
+                                       for (int i = index + 1; i < toolstrips.Count; i++)
+                                               if (toolstrips[i].TopLevelControl == ts.TopLevelControl && !(toolstrips[i] is StatusStrip))
+                                                       return toolstrips[i];
+
+                                       // Look for any toolstrip before this one in the collection
+                                       for (int i = 0; i < index; i++)
+                                               if (toolstrips[i].TopLevelControl == ts.TopLevelControl && !(toolstrips[i] is StatusStrip))
+                                                       return toolstrips[i];
+                               } else {
+                                       // Look for any toolstrip before this one in the collection
+                                       for (int i = index - 1; i >= 0; i--)
+                                               if (toolstrips[i].TopLevelControl == ts.TopLevelControl && !(toolstrips[i] is StatusStrip))
+                                                       return toolstrips[i];
+
+                                       // Look for any toolstrip after this one in the collection
+                                       for (int i = toolstrips.Count - 1; i > index; i--)
+                                               if (toolstrips[i].TopLevelControl == ts.TopLevelControl && !(toolstrips[i] is StatusStrip))
+                                                       return toolstrips[i];
+                               }
+                       }
+                       
+                       return null;
+               }
+               
                internal static bool ProcessCmdKey (ref Message m, Keys keyData)
                {
                        lock (menu_items)
@@ -417,6 +439,43 @@ namespace System.Windows.Forms
                        return false;
                }
                
+               internal static bool ProcessMenuKey (ref Message m)
+               {
+                       // If we have a currently active menu, deactivate it
+                       if (Application.KeyboardCapture != null) {
+                               if (Application.KeyboardCapture.OnMenuKey ())
+                                       return true;
+                       }
+                       
+                       // Get the parent form of this message
+                       Form f = (Form)Control.FromHandle (m.HWnd).TopLevelControl;
+
+                       // Check the MainMenuStrip property first
+                       if (f.MainMenuStrip != null)
+                               if (f.MainMenuStrip.OnMenuKey ())
+                                       return true;
+                                       
+                       // Look for any MenuStrip in the form
+                       lock (toolstrips)
+                               foreach (ToolStrip ts in toolstrips)
+                                       if (ts.TopLevelControl == f)
+                                               if (ts.OnMenuKey ())
+                                                       return true;
+
+                       return false;
+               }
+               
+               internal static void SetActiveToolStrip (ToolStrip toolStrip)
+               {
+                       if (Application.KeyboardCapture != null)
+                               Application.KeyboardCapture.KeyboardActive = false;
+                               
+                       if (toolStrip == null)
+                               return;
+                               
+                       toolStrip.KeyboardActive = true;
+               }
+               
                internal static void AddToolStripMenuItem (ToolStripMenuItem tsmi)
                {
                        lock (menu_items)
@@ -438,16 +497,25 @@ namespace System.Windows.Forms
                internal static void FireAppClicked ()
                {
                        if (AppClicked != null) AppClicked (null, EventArgs.Empty);
+                       
+                       if (Application.KeyboardCapture != null)
+                               Application.KeyboardCapture.KeyboardActive = false;
                }
 
                internal static void FireAppFocusChanged (Form form)
                {
                        if (AppFocusChange != null) AppFocusChange (form, EventArgs.Empty);
+
+                       if (Application.KeyboardCapture != null)
+                               Application.KeyboardCapture.KeyboardActive = false;
                }
 
                internal static void FireAppFocusChanged (object sender)
                {
                        if (AppFocusChange != null) AppFocusChange (sender, EventArgs.Empty);
+
+                       if (Application.KeyboardCapture != null)
+                               Application.KeyboardCapture.KeyboardActive = false;
                }
                
                private static void OnRendererChanged (EventArgs e)
index d18596d0571f9044e4043783209b7cacb6ed8b5e..56738ec8820d02cdaa75b1b35cb768cba443c61f 100644 (file)
@@ -39,6 +39,7 @@ namespace System.Windows.Forms
        {
                private CheckState checked_state;
                private bool check_on_click;
+               private bool close_on_mouse_release;
                private string shortcut_display_string;
                private Keys shortcut_keys = Keys.None;
                private bool show_shortcut_keys = true;
@@ -227,31 +228,11 @@ namespace System.Windows.Forms
                        if (!this.Enabled)
                                return;
                                
-                       if (this.IsOnDropDown) {
-                               if (this.HasDropDownItems)
-                                       return;
-
-                               this.HideDropDown (ToolStripDropDownCloseReason.ItemClicked);
+                       if (this.HasDropDownItems)
+                               return;
                                
-                               (this.Parent as ToolStripDropDown).Close (ToolStripDropDownCloseReason.ItemClicked);
-                               ToolStripManager.FireAppFocusChanged (this.Parent);
-
-                               Object parent = this.Parent;
-
-                               // Find the top level MenuStrip to inform it to close all open
-                               // dropdowns because this one was clicked
-                               while (parent != null) {
-                                       if (parent is MenuStrip)
-                                               (parent as MenuStrip).HideMenus (true, ToolStripDropDownCloseReason.ItemClicked);
-
-                                       if (parent is ToolStripDropDown)
-                                               parent = (parent as ToolStripDropDown).OwnerItem;
-                                       else if (parent is ToolStripItem)
-                                               parent = (parent as ToolStripItem).Parent;
-                                       else
-                                               break;
-                               }
-                       }
+                       if (this.IsOnDropDown)
+                               this.GetTopLevelToolStrip ().Dismiss (ToolStripDropDownCloseReason.ItemClicked);
 
                        if (this.IsMdiWindowListEntry) {
                                this.mdi_client_form.MdiParent.MdiContainer.ActivateChild (this.mdi_client_form);
@@ -281,6 +262,9 @@ namespace System.Windows.Forms
 
                protected override void OnMouseDown (MouseEventArgs e)
                {
+                       if (!this.IsOnDropDown && this.HasDropDownItems && this.DropDown.Visible)
+                               this.close_on_mouse_release = true;
+                               
                        if (this.HasDropDownItems && Enabled)
                                if (!this.DropDown.Visible)
                                        this.ShowDropDown ();
@@ -303,6 +287,15 @@ namespace System.Windows.Forms
 
                protected override void OnMouseUp (MouseEventArgs e)
                {
+                       if (this.close_on_mouse_release) {
+                               this.DropDown.Dismiss (ToolStripDropDownCloseReason.ItemClicked);
+                               this.Invalidate ();
+                               this.close_on_mouse_release = false;
+                               
+                               if (!this.IsOnDropDown)
+                                       (this.Parent as MenuStrip).MenuDroppedDown = false;
+                       }
+                               
                        if (!this.HasDropDownItems && Enabled)
                                base.OnMouseUp (e);
                }
@@ -320,10 +313,7 @@ namespace System.Windows.Forms
                                Color font_color = this.Enabled ? this.ForeColor : SystemColors.GrayText;
                                Image draw_image = this.Enabled ? this.Image : ToolStripRenderer.CreateDisabledImage (this.Image);
 
-                               if (this.IsOnDropDown)
-                                       this.Owner.Renderer.DrawMenuItemBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
-                               else
-                                       this.Owner.Renderer.DrawButtonBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
+                               this.Owner.Renderer.DrawMenuItemBackground (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
 
                                Rectangle text_layout_rect;
                                Rectangle image_layout_rect;
@@ -428,6 +418,19 @@ namespace System.Windows.Forms
                        
                        return key_string;
                }
+               
+               internal void HandleAutoExpansion ()
+               {
+                       if (this.HasDropDownItems) {
+                               this.ShowDropDown ();
+                               this.DropDown.SelectNextToolStripItem (null, true);
+                       }
+               }
+
+               internal override void HandleClick (EventArgs e)
+               {
+                       this.OnClick (e);
+               }
                #endregion
        }
 }
index 38740d3f9aa1bbca53e0d947a6ef110c14b9e29e..251063e9dfdc2f1e8ad3d6d65776cdb4b2071cd9 100644 (file)
@@ -131,9 +131,6 @@ namespace System.Windows.Forms
                        if (e.Item.Selected && !e.Item.Pressed)
                                using (Pen p = new Pen (this.ColorTable.ButtonSelectedBorder))
                                        e.Graphics.DrawRectangle (p, paint_here);
-                       else if (e.Item.Pressed && (e.Item.Owner is MenuStrip && (e.Item as ToolStripMenuItem).HasDropDownItems) && (e.Item as ToolStripMenuItem).DropDown.Visible == true)
-                               using (Pen p = new Pen (this.ColorTable.MenuBorder))
-                                       e.Graphics.DrawRectangle (p, paint_here);
                        else if (e.Item.Pressed)
                                using (Pen p = new Pen (this.ColorTable.ButtonPressedBorder))
                                        e.Graphics.DrawRectangle (p, paint_here);
@@ -276,20 +273,45 @@ namespace System.Windows.Forms
                protected override void OnRenderMenuItemBackground (ToolStripItemRenderEventArgs e)
                {
                        base.OnRenderMenuItemBackground (e);
+                       
+                       ToolStripMenuItem tsmi = (ToolStripMenuItem)e.Item;
+                       Rectangle paint_here;
 
-                       Rectangle paint_here = new Rectangle (1, 0, e.Item.Bounds.Width - 3, e.Item.Bounds.Height - 1);
-
-                       if (e.Item.Selected || e.Item.Pressed) {                //|| (e.Item is ToolStripMenuItem && (e.Item as ToolStripMenuItem).DropDown.Visible)) {
-                               if (this.ColorTable.UseSystemColors) {
+                       if (tsmi.IsOnDropDown) {
+                               paint_here = new Rectangle (1, 0, e.Item.Bounds.Width - 3, e.Item.Bounds.Height - 1);
+                               
+                               if (e.Item.Selected || e.Item.Pressed)
                                        if (e.Item.Enabled)
                                                e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (this.ColorTable.MenuItemSelectedGradientEnd), paint_here);
+
+                               if (tsmi.Selected || tsmi.Pressed)
+                                       using (Pen p = new Pen (this.ColorTable.MenuItemBorder))
+                                               e.Graphics.DrawRectangle (p, paint_here);
+                       }
+                       else {
+                               paint_here = new Rectangle (0, 0, e.Item.Width, e.Item.Height);
+
+                               if (e.Item.Pressed)
+                                       using (Brush b = new LinearGradientBrush (paint_here, this.ColorTable.ToolStripGradientBegin, this.ColorTable.ToolStripGradientEnd, LinearGradientMode.Vertical))
+                                               e.Graphics.FillRectangle (b, paint_here);
+                               else if (e.Item.Selected)
+                                       using (Brush b = new LinearGradientBrush (paint_here, this.ColorTable.ButtonSelectedGradientBegin, this.ColorTable.ButtonSelectedGradientEnd, LinearGradientMode.Vertical))
+                                               e.Graphics.FillRectangle (b, paint_here);
+                               else if (e.Item.BackColor != Control.DefaultBackColor && e.Item.BackColor != Color.Empty)
+                                       using (Brush b = new SolidBrush (e.Item.BackColor))
+                                               e.Graphics.FillRectangle (b, paint_here);
+
+                               paint_here.Width -= 1;
+                               paint_here.Height -= 1;
+
+                               if (tsmi.Selected || tsmi.Pressed) {
+                                       if (tsmi.HasDropDownItems && tsmi.DropDown.Visible)
+                                               using (Pen p = new Pen (this.ColorTable.MenuBorder))
+                                                       e.Graphics.DrawRectangle (p, paint_here);                               
+                                       else
+                                               using (Pen p = new Pen (this.ColorTable.MenuItemBorder))
+                                                       e.Graphics.DrawRectangle (p, paint_here);
                                }
-                               else
-                                       if (e.Item.Enabled)
-                                               e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (this.ColorTable.MenuItemSelectedGradientEnd), paint_here);
-                               
-                               using (Pen p = new Pen (this.ColorTable.MenuItemBorder))
-                                       e.Graphics.DrawRectangle (p, paint_here);                               
                        }
                }
 
index e52e65eb29e200cb51aa55f578f018c488a4c834..a3f7674fe20b75cc0e70d1f60387409832e5c939 100644 (file)
@@ -39,6 +39,7 @@ namespace System.Windows.Forms
        public class ToolStripSplitButton : ToolStripDropDownItem
        {
                private bool button_pressed;
+               private ToolStripItem default_item;
                private bool drop_down_button_selected;
                private int drop_down_button_width;
                
@@ -103,6 +104,16 @@ namespace System.Windows.Forms
                        get { return base.Selected; }
                }
 
+               public ToolStripItem DefaultItem {
+                       get { return this.default_item; }
+                       set {
+                               if (this.default_item != value) {
+                                       this.default_item = value;
+                                       this.OnDefaultItemChanged (EventArgs.Empty);
+                               }
+                       }
+               }
+               
                [Browsable (false)]
                public Rectangle DropDownButtonBounds {
                        get { return new Rectangle (this.Bounds.Right - this.drop_down_button_width, this.Bounds.Top, this.drop_down_button_width, this.Bounds.Height); }
@@ -268,6 +279,15 @@ namespace System.Windows.Forms
                        }
                }
 
+               protected internal override bool ProcessDialogKey (Keys keyData)
+               {
+                       if (this.Selected && keyData == Keys.Enter && this.DefaultItem != null) {
+                               this.DefaultItem.FireEvent (EventArgs.Empty, ToolStripItemEventType.Click);
+                               return true;
+                       }
+
+                       return base.ProcessDialogKey (keyData);
+               }
                #endregion
                
                #region Public Events