// // MenuStrip.cs // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (c) 2006 Jonathan Pobst // // Authors: // Jonathan Pobst (monkey@jpobst.com) // #if NET_2_0 using System; using System.Drawing; using System.ComponentModel; using System.Runtime.InteropServices; namespace System.Windows.Forms { [ClassInterface (ClassInterfaceType.AutoDispatch)] [ComVisible (true)] public class MenuStrip : ToolStrip { private ToolStripMenuItem mdi_window_list_item; public MenuStrip () : base () { base.CanOverflow = false; this.GripStyle = ToolStripGripStyle.Hidden; this.Stretch = true; this.Dock = DockStyle.Top; } #region Public Properties [DefaultValue (false)] [Browsable (false)] public new bool CanOverflow { get { return base.CanOverflow; } set { base.CanOverflow = value; } } [DefaultValue (ToolStripGripStyle.Hidden)] public new ToolStripGripStyle GripStyle { get { return base.GripStyle; } set { base.GripStyle = value; } } [DefaultValue (null)] [MergableProperty (false)] public ToolStripMenuItem MdiWindowListItem { get { return this.mdi_window_list_item; } set { if (this.mdi_window_list_item != value) { this.mdi_window_list_item = value; this.RefreshMdiItems (); } } } [DefaultValue (false)] public new bool ShowItemToolTips { get { return base.ShowItemToolTips; } set { base.ShowItemToolTips = value; } } [DefaultValue (true)] public new bool Stretch { get { return base.Stretch; } set { base.Stretch = value; } } #endregion #region Protected Properties protected override Padding DefaultGripMargin { get { return new Padding (2, 2, 0, 2); } } protected override Padding DefaultPadding { get { return new Padding (6, 2, 0, 2); } } protected override bool DefaultShowItemToolTips { get { return false; } } protected override Size DefaultSize { get { return new Size (200, 24); } } #endregion #region Protected Methods protected internal override ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick) { return new ToolStripMenuItem (text, image, onClick); } protected virtual void OnMenuActivate (EventArgs e) { EventHandler eh = (EventHandler)(Events [MenuActivateEvent]); if (eh != null) eh (this, e); } protected virtual void OnMenuDeactivate (EventArgs e) { EventHandler eh = (EventHandler)(Events [MenuDeactivateEvent]); if (eh != null) eh (this, e); } protected override bool ProcessCmdKey (ref Message msg, Keys keyData) { return base.ProcessCmdKey (ref msg, keyData); } protected override void WndProc (ref Message m) { base.WndProc (ref m); } #endregion #region Public Events static object MenuActivateEvent = new object (); static object MenuDeactivateEvent = new object (); public event EventHandler MenuActivate { add { Events.AddHandler (MenuActivateEvent, value); } remove { Events.RemoveHandler (MenuActivateEvent, value); } } public event EventHandler MenuDeactivate { add { Events.AddHandler (MenuDeactivateEvent, value); } remove { Events.RemoveHandler (MenuDeactivateEvent, value); } } #endregion #region Internal Methods internal void FireMenuActivate () { // The tracker lets us know when the form is clicked or loses focus ToolStripManager.AppClicked += new EventHandler (ToolStripMenuTracker_AppClicked); ToolStripManager.AppFocusChange += new EventHandler (ToolStripMenuTracker_AppFocusChange); this.OnMenuActivate (EventArgs.Empty); } internal void FireMenuDeactivate () { // Detach from the tracker ToolStripManager.AppClicked -= new EventHandler (ToolStripMenuTracker_AppClicked); ; ToolStripManager.AppFocusChange -= new EventHandler (ToolStripMenuTracker_AppFocusChange); this.OnMenuDeactivate (EventArgs.Empty); } private void ToolStripMenuTracker_AppFocusChange (object sender, EventArgs e) { this.HideMenus (true, ToolStripDropDownCloseReason.AppFocusChange); } private void ToolStripMenuTracker_AppClicked (object sender, EventArgs e) { this.HideMenus (true, ToolStripDropDownCloseReason.AppClicked); } internal void RefreshMdiItems () { if (this.mdi_window_list_item == null) return; Form parent_form = this.FindForm (); if (parent_form == null || parent_form.MainMenuStrip != this) return; MdiClient mdi = parent_form.MdiContainer; // Make a copy so we can delete from the real one ToolStripItem[] loopitems = new ToolStripItem[this.mdi_window_list_item.DropDownItems.Count]; this.mdi_window_list_item.DropDownItems.CopyTo (loopitems, 0); // If the mdi child has been removed, remove our menu item foreach (ToolStripItem tsi in loopitems) if (tsi is ToolStripMenuItem && (tsi as ToolStripMenuItem).IsMdiWindowListEntry) if (!mdi.mdi_child_list.Contains ((tsi as ToolStripMenuItem).MdiClientForm) || !(tsi as ToolStripMenuItem).MdiClientForm.Visible) this.mdi_window_list_item.DropDownItems.Remove (tsi); // Add the new forms and update state for (int i = 0; i < mdi.mdi_child_list.Count; i++) { Form mdichild = (Form)mdi.mdi_child_list[i]; ToolStripMenuItem tsi; if (!mdichild.Visible) continue; if ((tsi = FindMdiMenuItemOfForm (mdichild)) == null) { if (CountMdiMenuItems () == 0 && this.mdi_window_list_item.DropDownItems.Count > 0) this.mdi_window_list_item.DropDownItems.Add (new ToolStripSeparator ()); tsi = new ToolStripMenuItem (); tsi.MdiClientForm = mdichild; this.mdi_window_list_item.DropDownItems.Add (tsi); } tsi.Text = string.Format ("&{0} {1}", i + 1, mdichild.Text); tsi.Checked = parent_form.ActiveMdiChild == mdichild; } // Check that everything is in the correct order if (NeedToReorderMdi ()) ReorderMdiMenu (); } private ToolStripMenuItem FindMdiMenuItemOfForm (Form f) { // Not terribly efficient, but Mdi window lists shouldn't get too big foreach (ToolStripItem tsi in this.mdi_window_list_item.DropDownItems) if (tsi is ToolStripMenuItem && (tsi as ToolStripMenuItem).MdiClientForm == f) return (ToolStripMenuItem)tsi; return null; } private int CountMdiMenuItems () { int count = 0; foreach (ToolStripItem tsi in this.mdi_window_list_item.DropDownItems) if (tsi is ToolStripMenuItem && (tsi as ToolStripMenuItem).IsMdiWindowListEntry) count++; return count; } private bool NeedToReorderMdi () { // Mdi menus must be: User Items, Separator, Mdi Items bool seenMdi = false; foreach (ToolStripItem tsi in this.mdi_window_list_item.DropDownItems) { if (tsi is ToolStripMenuItem) { if (!(tsi as ToolStripMenuItem).IsMdiWindowListEntry) { if (seenMdi) return true; } else seenMdi = true; } } return false; } private void ReorderMdiMenu () { ToolStripItem[] loopitems = new ToolStripItem[this.mdi_window_list_item.DropDownItems.Count]; this.mdi_window_list_item.DropDownItems.CopyTo (loopitems, 0); this.mdi_window_list_item.DropDownItems.Clear (); foreach (ToolStripItem tsi in loopitems) if (tsi is ToolStripSeparator || !(tsi as ToolStripMenuItem).IsMdiWindowListEntry) this.mdi_window_list_item.DropDownItems.Add (tsi); int count = this.mdi_window_list_item.DropDownItems.Count; if (count > 0 && !(this.mdi_window_list_item.DropDownItems[count - 1] is ToolStripSeparator)) this.mdi_window_list_item.DropDownItems.Add (new ToolStripSeparator ()); foreach (ToolStripItem tsi in loopitems) if (tsi is ToolStripMenuItem && (tsi as ToolStripMenuItem).IsMdiWindowListEntry) this.mdi_window_list_item.DropDownItems.Add (tsi); } #endregion } } #endif