ToolStripMenuItem.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ToolStripMenuItem.cs / 1305376 / ToolStripMenuItem.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Windows.Forms {
    using System; 
    using System.Collections; 
    using System.ComponentModel;
    using System.Drawing; 
    using Microsoft.Win32;
    using System.Drawing.Imaging;
    using System.Threading;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Forms.Layout; 
    using System.Security; 
    using System.Security.Permissions;
    using System.Runtime.InteropServices; 
    using System.ComponentModel.Design.Serialization;
    using System.Windows.Forms.Design;
    using System.Globalization;
    using System.Windows.Forms.Internal; 
    using System.Runtime.Versioning;
 
    ///  
    /// 
    /// ToolStripMenuItem 
    /// 
    [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.MenuStrip | ToolStripItemDesignerAvailability.ContextMenuStrip)]
    [DesignerSerializer("System.Windows.Forms.Design.ToolStripMenuItemCodeDomSerializer, " + AssemblyRef.SystemDesign, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + AssemblyRef.SystemDesign)]
    public class ToolStripMenuItem : ToolStripDropDownItem { 

        private static MenuTimer menuTimer                             = new MenuTimer(); 
 
        private static readonly int PropShortcutKeys                   = PropertyStore.CreateKey();
        private static readonly int PropCheckState                     = PropertyStore.CreateKey(); 
        private static readonly int PropMdiForm                        = PropertyStore.CreateKey();

        private bool checkOnClick                                      = false;
        private bool showShortcutKeys                                  = true; 
        private ToolStrip lastOwner                                    = null;
 
        // SUPPORT for mapping NATIVE menu commands to ToolStripMenuItems ----- 
        // corresponds to wID in MENUITEMINFO structure
        private int     nativeMenuCommandID                               = -1; 
        private IntPtr  targetWindowHandle                                = IntPtr.Zero;
        private IntPtr  nativeMenuHandle                                  = IntPtr.Zero;

        // Keep checked images shared between menu items, but per thread so we dont have locking issues in GDI+ 
        [ThreadStatic]
        private static Image indeterminateCheckedImage; 
 
        [ThreadStatic]
        private static Image checkedImage; 

        private string shortcutKeyDisplayString;
        private string cachedShortcutText;
        private Size cachedShortcutSize = Size.Empty; 

 
        private byte openMouseId = 0; 

        private static readonly object EventCheckedChanged = new object(); 
        private static readonly object EventCheckStateChanged = new object();

        /// 
        public ToolStripMenuItem() : base() { 
            Initialize(); // all additional work should be done in Initialize
        } 
        public ToolStripMenuItem(string text):base(text,null,(EventHandler)null) { 
            Initialize();
        } 
        public ToolStripMenuItem(Image image):base(null,image,(EventHandler)null) {
            Initialize();
        }
        public ToolStripMenuItem(string text, Image image):base(text,image,(EventHandler)null) { 
            Initialize();
        } 
        public ToolStripMenuItem(string text, Image image, EventHandler onClick):base(text,image,onClick) { 
            Initialize();
        } 
        public ToolStripMenuItem(string text, Image image, EventHandler onClick, string name) : base(text,image,onClick, name){
            Initialize();
        }
        public ToolStripMenuItem(string text, Image image, params ToolStripItem[] dropDownItems):base(text,image,dropDownItems) { 
            Initialize();
        } 
        public ToolStripMenuItem(string text, Image image, EventHandler onClick, Keys shortcutKeys):base(text,image,onClick) { 
            Initialize();
            this.ShortcutKeys = shortcutKeys; 
        }
        internal ToolStripMenuItem(Form mdiForm) {
            Initialize();
            Properties.SetObject(PropMdiForm,mdiForm); 
        }
 
        ///  this constructor is only used when we're trying to 
        ///          mimic a native menu like the system menu.  In that case
        ///          we've got to go ahead and collect the command id and the 
        ///          target window to send WM_COMMAND/WM_SYSCOMMAND messages to.
        /// 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        internal ToolStripMenuItem(IntPtr hMenu, int nativeMenuCommandId, IWin32Window targetWindow) { 
            Initialize();
            this.Overflow                   = ToolStripItemOverflow.Never; 
            this.nativeMenuCommandID        = nativeMenuCommandId; 
            this.targetWindowHandle         = Control.GetSafeHandle(targetWindow);
            this.nativeMenuHandle           = hMenu; 

            // Since fetching the image and the text is an awful lot of work
            // we're going to just cache it and assume the native stuff
            // doesnt update. 
            // we'll only live-update enabled.
            // if this becomes a problem we can override Image and Text properties 
            // to live-return the results. 

            // fetch image 
            this.Image = GetNativeMenuItemImage();
            this.ImageScaling = ToolStripItemImageScaling.None;

            // fetch text 
            string text = GetNativeMenuItemTextAndShortcut();
 
            // the shortcut is tab separated from the item text. 
            if (text != null) {
                // separate out the two fields. 
                string[] textFields = text.Split('\t');

                if (textFields.Length >= 1){
                    this.Text = textFields[0]; 
                }
 
                if (textFields.Length >= 2) { 
                    // VSWhidbey 448242: We dont care about the shortcut here, the OS is going to
                    // handle it for us by sending a WM_(SYS)COMMAND during TranslateAcellerator 
                    // Just display whatever the OS would have.
                    this.ShowShortcutKeys = true;
                    this.ShortcutKeyDisplayString = textFields[1];
                } 
            }
        } 
 
        internal override void AutoHide(ToolStripItem otherItemBeingSelected) {
            if (IsOnDropDown) { 
                MenuTimer.Transition(this,otherItemBeingSelected as ToolStripMenuItem);
            }
            else {
                base.AutoHide(otherItemBeingSelected); 
            }
        } 
        private void ClearShortcutCache() { 
            cachedShortcutSize = Size.Empty;
            cachedShortcutText = null; 
        }

        /// 
        protected override ToolStripDropDown CreateDefaultDropDown() { 
            // AutoGenerate a Winbar DropDown - set the property so we hook events
             return new ToolStripDropDownMenu(this, true); 
        } 

        internal override ToolStripItemInternalLayout CreateInternalLayout() { 
              return new ToolStripMenuItemInternalLayout(this);
        }

        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override AccessibleObject CreateAccessibilityInstance() {
            return new ToolStripMenuItemAccessibleObject(this); 
        } 

        private void Initialize() { 
            this.Overflow                   = ToolStripItemOverflow.Never;
            this.MouseDownAndUpMustBeInSameItem = false;
            this.SupportsDisabledHotTracking = true;
        } 

        ///  
        ///  
        /// Deriving classes can override this to configure a default size for their control.
        /// This is more efficient than setting the size in the control's constructor. 
        /// 
        protected override Size DefaultSize {
            get {
                return new Size(32, 19); 
            }
        } 
 

        ///  
        protected internal override Padding DefaultMargin {
            get {
                 return Padding.Empty;
            } 
        }
        ///  
        protected override Padding DefaultPadding { 
            get {
                if (IsOnDropDown) { 
                    return new Padding(0, 1, 0, 1);
                }
                else {
                    return new Padding(4, 0, 4, 0); 
                }
            } 
        } 

 
        public override bool Enabled {
           get{
                if (nativeMenuCommandID != -1) {
                    // if we're based off a native menu item, 
                    // we need to ask it if it's enabled.
                    if (base.Enabled && nativeMenuHandle != IntPtr.Zero && targetWindowHandle != IntPtr.Zero) { 
                        return GetNativeMenuItemEnabled(); 
                    }
                    return false; 
                }
                else {
                    return base.Enabled;
                } 
           }
           set { 
                base.Enabled = value; 
           }
        } 

        /// 
        /// 
        ///  
        /// Gets or sets a value indicating whether the item is checked.
        ///  
        ///  
        [
        Bindable(true), 
        DefaultValue(false),
        SRCategory(SR.CatAppearance),
        RefreshProperties(RefreshProperties.All),
        SRDescription(SR.CheckBoxCheckedDescr) 
        ]
        public bool Checked { 
            get { 
                return CheckState != CheckState.Unchecked;
            } 

            set {
                if (value != Checked) {
                    CheckState = value ? CheckState.Checked : CheckState.Unchecked; 
                    InvokePaint();
                } 
            } 
        }
 

        /// 
        /// Keeps a shared copy of the checked image between all menu items
        /// Fishes out the appropriate one based on CheckState. 
        /// 
        internal Image CheckedImage { 
            [ResourceExposure(ResourceScope.Machine)] 
            [ResourceConsumption(ResourceScope.Machine)]
            get { 
                CheckState checkedState = CheckState;

                if (checkedState == CheckState.Indeterminate) {
                    if (indeterminateCheckedImage == null) { 
                        Bitmap indeterminateCheckedBmp = new Bitmap(typeof(ToolStripMenuItem), "IndeterminateChecked.bmp");
                        if (indeterminateCheckedBmp != null) { 
                            // 
                            indeterminateCheckedBmp.MakeTransparent(indeterminateCheckedBmp.GetPixel(1,1));
                            indeterminateCheckedImage = indeterminateCheckedBmp; 
                        }
                    }
                    return indeterminateCheckedImage;
                } 
                else if (checkedState == CheckState.Checked)  {
                    if (checkedImage == null) { 
                        Bitmap checkedBmp = new Bitmap(typeof(ToolStripMenuItem), "Checked.bmp"); 
                         if (checkedBmp != null) {
                            // 
                            checkedBmp.MakeTransparent(checkedBmp.GetPixel(1,1));
                            checkedImage = checkedBmp;
                        }
                    } 
                    return checkedImage;
                } 
                return null; 

            } 
        }


         ///  
         [
         DefaultValue(false), 
         SRCategory(SR.CatBehavior), 
         SRDescription(SR.ToolStripButtonCheckOnClickDescr)
         ] 
         public bool CheckOnClick {
             get {
                 return checkOnClick;
             } 
             set {
                 checkOnClick = value; 
             } 
         }
 
        /// 
        /// 
        /// Gets
        /// or sets a value indicating whether the check box is checked. 
        /// 
        [ 
        Bindable(true), 
        SRCategory(SR.CatAppearance),
        DefaultValue(CheckState.Unchecked), 
        RefreshProperties(RefreshProperties.All),
        SRDescription(SR.CheckBoxCheckStateDescr)
        ]
        public CheckState CheckState { 
            get {
                bool found = false; 
                object checkState = Properties.GetInteger(PropCheckState, out found); 
                return (found) ? (CheckState)checkState : CheckState.Unchecked;
            } 

            set {
                //valid values are 0x0 to 0x2
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)CheckState.Unchecked, (int)CheckState.Indeterminate)) 
                {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(CheckState)); 
                } 

                if (value != CheckState) { 
                    Properties.SetInteger(PropCheckState, (int)value);
                    OnCheckedChanged(EventArgs.Empty);
                    OnCheckStateChanged(EventArgs.Empty);
                } 
            }
        } 
 
        /// 
        ///  
        /// Occurs when the
        /// value of the 
        /// property changes.
        ///  
        [SRDescription(SR.CheckBoxOnCheckedChangedDescr)]
        public event EventHandler CheckedChanged { 
            add { 
                Events.AddHandler(EventCheckedChanged, value);
            } 
            remove {
                Events.RemoveHandler(EventCheckedChanged, value);
            }
        } 
        /// 
        ///  
        /// Occurs when the 
        /// value of the 
        /// property changes. 
        /// 
        [SRDescription(SR.CheckBoxOnCheckStateChangedDescr)]
        public event EventHandler CheckStateChanged {
            add { 
                Events.AddHandler(EventCheckStateChanged, value);
            } 
            remove { 
                Events.RemoveHandler(EventCheckStateChanged, value);
            } 
        }


        ///  
        /// 
        /// Specifies whether or not the item is glued to the winbar or overflow or 
        /// can float between the two. 
        /// 
        [ 
        DefaultValue(ToolStripItemOverflow.Never),
        SRDescription(SR.ToolStripItemOverflowDescr),
        SRCategory(SR.CatLayout)
     	] 
        public new ToolStripItemOverflow Overflow {
            get { 
                return base.Overflow; 
            }
            set { 
                base.Overflow = value;
            }
        }
 
        /// 
        ///  
        ///  
        /// Gets or sets the shortcut keys associated with the menu
        /// item. 
        /// 
        /// 
        [
        Localizable(true), 
        DefaultValue(Keys.None),
        SRDescription(SR.MenuItemShortCutDescr) 
        ] 
        public Keys ShortcutKeys {
            get { 
                bool found = false;
                object shortcutKeys = Properties.GetInteger(PropShortcutKeys, out found );
                return (found) ? (Keys)shortcutKeys : Keys.None;
            } 
            set {
                if ((value != Keys.None) && !ToolStripManager.IsValidShortcut(value)){ 
                    // prevent use of alt, ctrl, shift modifiers with no key code. 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(Keys));
                } 
                Keys originalShortcut = ShortcutKeys;
                if (originalShortcut != value) {
                    ClearShortcutCache();
                    ToolStrip owner = this.Owner; 
                    if (owner != null) {
                        // add to the shortcut caching system. 
                        if (originalShortcut != Keys.None) { 
                            owner.Shortcuts.Remove(originalShortcut);
                        } 
                        if (owner.Shortcuts.Contains(value)) {
                            // last one in wins.
                            owner.Shortcuts[value] = this;
                        } 
                        else {
                            owner.Shortcuts.Add(value, this); 
                        } 
                    }
                    Properties.SetInteger(PropShortcutKeys, (int)value); 

                    if (ShowShortcutKeys && IsOnDropDown) {
                        ToolStripDropDownMenu parent = GetCurrentParentDropDown() as ToolStripDropDownMenu;
                        if (parent != null) { 
                            LayoutTransaction.DoLayout(this.ParentInternal, this, "ShortcutKeys");
                            parent.AdjustSize(); 
                        } 
                    }
                } 
            }

        }
 
        [
        SRDescription(SR.ToolStripMenuItemShortcutKeyDisplayStringDescr), 
        SRCategory(SR.CatAppearance), 
        DefaultValue(null),
        Localizable(true) 
        ]
        public string ShortcutKeyDisplayString {
            get {
                return shortcutKeyDisplayString; 
            }
            set { 
                if (shortcutKeyDisplayString != value) { 
                    shortcutKeyDisplayString = value;
                    ClearShortcutCache(); 
                    if (ShowShortcutKeys) {
                        ToolStripDropDown parent = this.ParentInternal as ToolStripDropDown;
                        if (parent != null) {
                            LayoutTransaction.DoLayout(parent, this, "ShortcutKeyDisplayString"); 
                            parent.AdjustSize();
                        } 
                    } 
                }
            } 
        }

        /// 
        ///  
        /// 
        /// Gets or sets a value that indicates whether the shortcut 
        /// keys that are assocaited 
        /// with the menu item are displayed next to the menu item
        /// caption. 
        /// 
        /// 
        [
        DefaultValue(true), 
        Localizable(true),
        SRDescription(SR.MenuItemShowShortCutDescr) 
        ] 
        public bool ShowShortcutKeys {
            get { 
                return showShortcutKeys;
            }
            set {
                if (value != showShortcutKeys) { 
                   ClearShortcutCache();
                   showShortcutKeys = value; 
                   ToolStripDropDown parent = this.ParentInternal as ToolStripDropDown; 
                   if (parent != null) {
                        LayoutTransaction.DoLayout(parent, this, "ShortcutKeys"); 
                        parent.AdjustSize();

                    }
                } 
            }
        } 
 

        ///  
        /// An item is toplevel if it is parented to anything other than a ToolStripDropDownMenu
        /// This implies that a ToolStripMenuItem in an overflow IS a toplevel item
        /// 
        internal bool IsTopLevel { 
            get {
                return (this.ParentInternal as ToolStripDropDown == null); 
            } 
        }
 
        [Browsable(false)]
        public bool IsMdiWindowListEntry {
            get{
                return MdiForm != null; 
            }
        } 
 
        internal static MenuTimer MenuTimer {
            get { 
                return menuTimer;
            }
        }
 

        ///  Tag property for internal use  
        internal Form MdiForm { 
            get {
                if (Properties.ContainsObject(PropMdiForm)) { 
                    return Properties.GetObject(PropMdiForm) as Form;
                }
                return null;
 
            }
        } 
 
        internal ToolStripMenuItem Clone() {
 
            // dirt simple clone - just properties, no subitems

            ToolStripMenuItem menuItem = new ToolStripMenuItem();
            menuItem.Events.AddHandlers(this.Events); 

            menuItem.AccessibleName = this.AccessibleName; 
            menuItem.AccessibleRole = this.AccessibleRole; 
            menuItem.Alignment = this.Alignment;
            menuItem.AllowDrop = this.AllowDrop; 
            menuItem.Anchor = this.Anchor;
            menuItem.AutoSize = this.AutoSize;
            menuItem.AutoToolTip = this.AutoToolTip;
            menuItem.BackColor = this.BackColor; 
            menuItem.BackgroundImage = this.BackgroundImage;
            menuItem.BackgroundImageLayout = this.BackgroundImageLayout; 
            menuItem.Checked = this.Checked; 
            menuItem.CheckOnClick = this.CheckOnClick;
            menuItem.CheckState = this.CheckState; 
            menuItem.DisplayStyle = this.DisplayStyle;
            menuItem.Dock = this.Dock;
            menuItem.DoubleClickEnabled = this.DoubleClickEnabled;
            menuItem.Enabled = this.Enabled; 
            menuItem.Font = this.Font;
            menuItem.ForeColor = this.ForeColor; 
            menuItem.Image = this.Image; 
            menuItem.ImageAlign = this.ImageAlign;
            menuItem.ImageScaling = this.ImageScaling; 
            menuItem.ImageTransparentColor = this.ImageTransparentColor;
            menuItem.Margin = this.Margin;
            menuItem.MergeAction = this.MergeAction;
            menuItem.MergeIndex = this.MergeIndex; 
            menuItem.Name = this.Name;
            menuItem.Overflow = this.Overflow; 
            menuItem.Padding = this.Padding; 
            menuItem.RightToLeft= this.RightToLeft;
 
            // No settings support for cloned items.
            // menuItem.SaveSettings= this.SaveSettings;
            // menuItem.SettingsKey = this.SettingsKey;
 
            menuItem.ShortcutKeys = this.ShortcutKeys;
            menuItem.ShowShortcutKeys = this.ShowShortcutKeys; 
            menuItem.Tag = this.Tag; 
            menuItem.Text = this.Text;
            menuItem.TextAlign = this.TextAlign; 
            menuItem.TextDirection = this.TextDirection;
            menuItem.TextImageRelation = this.TextImageRelation;
            menuItem.ToolTipText = this.ToolTipText;
 
            // cant actually use "Visible" property as that returns whether or not the parent
            // is visible too.. instead use ParticipatesInLayout as this queries the actual state. 
            menuItem.Visible = ((IArrangedElement)this).ParticipatesInLayout; 

            if (!AutoSize) { 
                menuItem.Size = this.Size;
            }
            return menuItem;
       } 

        protected override void Dispose(bool disposing) { 
            if (disposing) { 
                if (lastOwner != null) {
                    Keys shortcut = this.ShortcutKeys; 
                    if (shortcut != Keys.None && lastOwner.Shortcuts.ContainsKey(shortcut)) {
                        lastOwner.Shortcuts.Remove(shortcut);
                    }
                    lastOwner = null; 
                    if (MdiForm != null) {
                        Properties.SetObject(PropMdiForm,null); 
                    } 

                } 
            }
            base.Dispose(disposing);
        }
 
        private bool GetNativeMenuItemEnabled() {
            if (nativeMenuCommandID == -1 || nativeMenuHandle == IntPtr.Zero) { 
                Debug.Fail("why were we called to fetch native menu item info with nothing assigned?"); 
                return false;
            } 
            NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW();
            info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW));
            info.fMask = NativeMethods.MIIM_STATE;
            info.fType = NativeMethods.MIIM_STATE; 
            info.wID = nativeMenuCommandID;
            UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/ false, info); 
 
            return ((info.fState & NativeMethods.MFS_DISABLED) == 0);
        } 

        // returns text and shortcut separated by tab.
        private string GetNativeMenuItemTextAndShortcut() {
 
            if (nativeMenuCommandID == -1 || nativeMenuHandle == IntPtr.Zero) {
                Debug.Fail("why were we called to fetch native menu item info with nothing assigned?"); 
                return null; 
            }
            string text = null; 

            // fetch the string length
            NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW();
            info.fMask = NativeMethods.MIIM_STRING; 
            info.fType = NativeMethods.MIIM_STRING;
            info.wID = nativeMenuCommandID; 
            info.dwTypeData = IntPtr.Zero; 
            UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/  false, info);
 
            if (info.cch > 0) {
                // fetch the string
                info.cch += 1;  // according to MSDN we need to increment the count we receive by 1.
                info.wID = nativeMenuCommandID; 
                IntPtr allocatedStringBuffer = Marshal.AllocCoTaskMem(info.cch * Marshal.SystemDefaultCharSize);
                info.dwTypeData = allocatedStringBuffer; 
 

                try { 
                    UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/  false, info);

                    // convert the string into managed data.
                	if (info.dwTypeData != IntPtr.Zero){ 
                        // we have to use PtrToStringAuto as we can't use Marshal.SizeOf to determine
                        // the size of the struct with a StringBuilder member. 
                        text = Marshal.PtrToStringAuto(info.dwTypeData, info.cch); 
                    }
                } 
                finally {
                   if (allocatedStringBuffer != IntPtr.Zero) {
                        // use our local instead of the info structure member *just* in case windows decides to clobber over it.
                        // we want to be sure to deallocate the memory we know we allocated. 
                        Marshal.FreeCoTaskMem(allocatedStringBuffer);
                    } 
                } 
            }
            return text; 
        }

        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine | ResourceScope.Process, ResourceScope.Machine | ResourceScope.Process)] 
        private Image GetNativeMenuItemImage(){
 
            if (nativeMenuCommandID == -1 || nativeMenuHandle == IntPtr.Zero) { 
                Debug.Fail("why were we called to fetch native menu item info with nothing assigned?");
                return null; 
            }

            NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW();
            info.fMask = NativeMethods.MIIM_BITMAP; 
            info.fType = NativeMethods.MIIM_BITMAP;
            info.wID = nativeMenuCommandID; 
            UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/ false, info); 

            if (info.hbmpItem != IntPtr.Zero && info.hbmpItem.ToInt32() > NativeMethods.HBMMENU_POPUP_MINIMIZE) { 
                return Bitmap.FromHbitmap(info.hbmpItem);
            }
            else {
                // its a system defined bitmap 
                int buttonToUse = -1;
 
                switch (info.hbmpItem.ToInt32()) { 
                    case NativeMethods.HBMMENU_MBAR_CLOSE:
                    case NativeMethods.HBMMENU_MBAR_CLOSE_D: 
                    case NativeMethods.HBMMENU_POPUP_CLOSE:
                        buttonToUse = (int)CaptionButton.Close;
                        break;
 
                    case NativeMethods.HBMMENU_MBAR_MINIMIZE:
                    case NativeMethods.HBMMENU_MBAR_MINIMIZE_D: 
                    case NativeMethods.HBMMENU_POPUP_MINIMIZE: 
                        buttonToUse = (int)CaptionButton.Minimize;
                        break; 

                    case NativeMethods.HBMMENU_MBAR_RESTORE:
                    case NativeMethods.HBMMENU_POPUP_RESTORE:
                        buttonToUse = (int)CaptionButton.Restore; 
                        break;
 
                    case NativeMethods.HBMMENU_POPUP_MAXIMIZE: 
                        buttonToUse = (int)CaptionButton.Maximize;
                        break; 

                    case NativeMethods.HBMMENU_SYSTEM:
                        //
                    case NativeMethods.HBMMENU_CALLBACK: 
                        // owner draw not supported
                        default: 
                        break; 
                }
                if (buttonToUse > -1) { 

                    // we've mapped to a system defined bitmap we know how to draw
                    Bitmap image = new Bitmap(16, 16);
 
                    using (Graphics g = Graphics.FromImage(image)) {
                        ControlPaint.DrawCaptionButton(g, new Rectangle(Point.Empty, image.Size), (CaptionButton)buttonToUse, ButtonState.Flat); 
                        g.DrawRectangle(SystemPens.Control, 0, 0, image.Width - 1, image.Height - 1); 
                    }
 
                    image.MakeTransparent(SystemColors.Control);
                    return image;
                }
            } 
            return null;
        } 
 

        internal Size GetShortcutTextSize() { 
             if (!ShowShortcutKeys) {
                return Size.Empty;
             }
             string shortcutString = GetShortcutText(); 
             if (string.IsNullOrEmpty(shortcutString)) {
                return Size.Empty; 
             } 
             else if (cachedShortcutSize == Size.Empty) {
                cachedShortcutSize = TextRenderer.MeasureText(shortcutString, Font); 
             }
             return cachedShortcutSize;
        }
 
        private string GetShortcutText() {
            if (cachedShortcutText == null) { 
                cachedShortcutText = ShortcutToText(this.ShortcutKeys, this.ShortcutKeyDisplayString); 
            }
            return cachedShortcutText; 
        }

        internal void HandleAutoExpansion() {
            if (Enabled && ParentInternal != null && ParentInternal.MenuAutoExpand && HasDropDownItems) { 
                ShowDropDown();
                DropDown.SelectNextToolStripItem(null, /*forward=*/true); 
            } 
        }
 
        /// 
        protected override void OnClick(EventArgs e) {
            if (checkOnClick) {
                this.Checked = !this.Checked; 
            }
            base.OnClick(e); 
            if (nativeMenuCommandID != -1) { 
                // fire off the appropriate native handler by posting a message to the window target.
                if ((nativeMenuCommandID & 0xF000) != 0) { 
                    // These are system menu items like Minimize, Maximize, Restore, Resize, Move, Close.

                    // use PostMessage instead of SendMessage so that the DefWndProc can appropriately handle
                    // the system message... if we use SendMessage the dismissal of our window 
                    // breaks things like the modal sizing loop.
                    UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), NativeMethods.WM_SYSCOMMAND,nativeMenuCommandID, 0); 
                } 
                else {
                    // These are user added items like ".Net Window..." 

                    // be consistent with sending a WM_SYSCOMMAND, use POST not SEND.
                    UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), NativeMethods.WM_COMMAND, nativeMenuCommandID, 0);
                } 
                this.Invalidate();
            } 
 
        }
 
        /// 
        /// 
        /// Raises the 
        /// event. 
        /// 
        protected virtual void OnCheckedChanged(EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventCheckedChanged]; 
            if (handler != null) handler(this,e);
        } 

        /// 
        /// 
        /// Raises the  event. 
        /// 
        protected virtual void OnCheckStateChanged(EventArgs e) { 
            AccessibilityNotifyClients(AccessibleEvents.StateChange); 
            EventHandler handler = (EventHandler)Events[EventCheckStateChanged];
            if (handler != null) handler(this,e); 
        }

        /// 
        protected override void OnDropDownHide(EventArgs e) { 

            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnDropDownHide] MenuTimer.Cancel called"); 
            MenuTimer.Cancel(this); 
            base.OnDropDownHide(e);
        } 

        protected override void OnDropDownShow(EventArgs e) {
            // if someone has beaten us to the punch by arrowing around
            // cancel the current menu timer. 
            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnDropDownShow] MenuTimer.Cancel called");
            MenuTimer.Cancel(this); 
            if (ParentInternal != null) { 
                ParentInternal.MenuAutoExpand = true;
            } 
            base.OnDropDownShow(e);
        }

        protected override void OnFontChanged(EventArgs e) { 
            ClearShortcutCache();
            base.OnFontChanged(e); 
        } 
        /// 
        internal void OnMenuAutoExpand() { 
            this.ShowDropDown();
        }

 
        /// 
        ///  
        protected override void OnMouseDown(MouseEventArgs e) { 

            // Opening should happen on mouse down 
            // we use a mouse down ID to ensure that the reshow

            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnMouseDown] MenuTimer.Cancel called");
            MenuTimer.Cancel(this); 
            OnMouseButtonStateChange(e, /*isMouseDown=*/true);
 
        } 

        protected override void OnMouseUp(MouseEventArgs e) { 
           OnMouseButtonStateChange(e, /*isMouseDown=*/false);
           base.OnMouseUp(e);
        }
 
        private void OnMouseButtonStateChange(MouseEventArgs e, bool isMouseDown) {
            bool showDropDown = true; 
            if (IsOnDropDown) { 
              ToolStripDropDown dropDown = GetCurrentParentDropDown() as ToolStripDropDown;
 
              // VSWhidbey 260536 - right click support for context menus.
              // used in ToolStripItem to determine whether to fire click OnMouseUp.
              SupportsRightClick = (dropDown.GetFirstDropDown() is ContextMenuStrip);
            } 
            else {
              showDropDown = !DropDown.Visible; 
              SupportsRightClick = false; 
            }
 
            if (e.Button == MouseButtons.Left ||
              (e.Button == MouseButtons.Right && SupportsRightClick)) {

                if (isMouseDown && showDropDown) { 
                    // opening should happen on mouse down.
                    Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID"); 
                    openMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId(); 
                    this.ShowDropDown(/*mousePush =*/true);
 
                }
                else if (!isMouseDown && !showDropDown) {
                    // closing should happen on mouse up.  ensure it's not the mouse
                    // up for the mouse down we opened with. 
                    Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID");
                    byte closeMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId(); 
                    int openedMouseID =openMouseId; 
                    if (closeMouseId != openedMouseID) {
                        openMouseId = 0;  // reset the mouse id, we should never get this value from toolstrip. 
                        ToolStripManager.ModalMenuFilter.CloseActiveDropDown(DropDown, ToolStripDropDownCloseReason.AppClicked);
                        Select();
                    }
 
                }
 
            } 
        }
 


        /// 
        ///  
        protected override void OnMouseEnter(EventArgs e) {
 
            Debug.Assert(this.ParentInternal != null, "Why is parent null"); 

            // If we are in a submenu pop down the submenu.		 
            if (this.ParentInternal != null && this.ParentInternal.MenuAutoExpand && Selected) {
                Debug.WriteLineIf(ToolStripItem.MouseDebugging.TraceVerbose, "received mouse enter - calling drop down");

                Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnMouseEnter] MenuTimer.Cancel / MenuTimer.Start called"); 

                MenuTimer.Cancel(this); 
                MenuTimer.Start(this); 

            } 
            base.OnMouseEnter(e);
        }

 
        /// 
        ///  
        protected override void OnMouseLeave(EventArgs e) { 
              Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnMouseLeave] MenuTimer.Cancel called");
              MenuTimer.Cancel(this); 
              base.OnMouseLeave(e);
        }

        protected override void OnOwnerChanged(EventArgs e) { 

            Keys shortcut = this.ShortcutKeys; 
            if (shortcut != Keys.None) { 
                if (lastOwner != null) {
                    lastOwner.Shortcuts.Remove(shortcut); 
                }

                if (Owner != null) {
                   if (Owner.Shortcuts.Contains(shortcut)) { 
                        // last one in wins
                        Owner.Shortcuts[shortcut] = this; 
                   } 
                   else {
                        Owner.Shortcuts.Add(shortcut, this); 
                   }
                   lastOwner = Owner;
                }
            } 

            base.OnOwnerChanged(e); 
        } 

        ///  
        /// 
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {

            if (this.Owner != null) { 
                ToolStripRenderer renderer = this.Renderer;
                Graphics g = e.Graphics; 
                renderer.DrawMenuItemBackground(new ToolStripItemRenderEventArgs(g, this)); 

                Color textColor = SystemColors.MenuText; 
                if (IsForeColorSet) {
                    textColor =  this.ForeColor;
                }
                else if (!this.IsTopLevel || (ToolStripManager.VisualStylesEnabled)) { 
                    if (Selected || Pressed) {
                        textColor = SystemColors.HighlightText; 
                    } 
                    else {
                        textColor =  SystemColors.MenuText; 
                    }
                }

                bool rightToLeft = (RightToLeft == RightToLeft.Yes); 

                ToolStripMenuItemInternalLayout menuItemInternalLayout = this.InternalLayout as ToolStripMenuItemInternalLayout; 
                if (menuItemInternalLayout != null && menuItemInternalLayout.UseMenuLayout) { 

                    // Support for special DropDownMenu layout 
                    #if DEBUG_PAINT
                        g.DrawRectangle(Pens.Green, menuItemInternalLayout.TextRectangle);
                        g.DrawRectangle(Pens.HotPink, menuItemInternalLayout.ImageRectangle);
                        g.DrawRectangle(Pens.Black, menuItemInternalLayout.CheckRectangle); 
                        g.DrawRectangle(Pens.Red, menuItemInternalLayout.ArrowRectangle);
                        g.DrawRectangle(Pens.Blue, new Rectangle(Point.Empty, new Size(-1,-1) + this.Size)); 
                    #endif 
                    if (CheckState != CheckState.Unchecked && menuItemInternalLayout.PaintCheck) {
                        Rectangle checkRectangle = menuItemInternalLayout.CheckRectangle; 
                        if (!menuItemInternalLayout.ShowCheckMargin) {
                            checkRectangle =  menuItemInternalLayout.ImageRectangle;
                        }
                        if (checkRectangle.Width != 0) { 
                            renderer.DrawItemCheck(new ToolStripItemImageRenderEventArgs(g, this, CheckedImage, checkRectangle));
                        } 
                    } 

 
                   if ((DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) {

                        // render text AND shortcut
                        renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, this.Text, InternalLayout.TextRectangle, textColor, this.Font, (rightToLeft) ? ContentAlignment.MiddleRight : ContentAlignment.MiddleLeft)); 
                        bool showShortCut = ShowShortcutKeys;
                        if (!DesignMode){ 
                            showShortCut = showShortCut && !HasDropDownItems; 
                        }
 
                        if (showShortCut) {
                            renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, GetShortcutText(), InternalLayout.TextRectangle, textColor, this.Font, (rightToLeft) ? ContentAlignment.MiddleLeft : ContentAlignment.MiddleRight));
                        }
                   } 

                    if (HasDropDownItems) { 
 
                        ArrowDirection arrowDir = (rightToLeft) ? ArrowDirection.Left : ArrowDirection.Right;
                        Color arrowColor = (Selected ||Pressed) ? SystemColors.HighlightText : SystemColors.MenuText; 
                        arrowColor = (Enabled) ? arrowColor : SystemColors.ControlDark;
                        renderer.DrawArrow(new ToolStripArrowRenderEventArgs(g, this, menuItemInternalLayout.ArrowRectangle, arrowColor, arrowDir));
                    }
 
                    if (menuItemInternalLayout.PaintImage && (DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image && Image != null) {
                       renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, InternalLayout.ImageRectangle)); 
                    } 

                } 
                else {


                    // Toplevel item support, menu items hosted on a plain winbar dropdown 
                    if ((DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) {
                        renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, this.Text, InternalLayout.TextRectangle, textColor, this.Font, InternalLayout.TextFormat)); 
                    } 

                    if ((DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image && Image != null) { 
                       renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, InternalLayout.ImageRectangle));
                    }
                }
 

            } 
 
        }
 
        /// 
        /// 
        /// handle shortcut keys here.
        ///  
        [
        SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ] 
        protected internal override bool ProcessCmdKey(ref Message m, Keys keyData) {
 
            if (Enabled && ShortcutKeys == keyData && !HasDropDownItems) {
                FireEvent(ToolStripItemEventType.Click);
                return true;
            } 

            // call base here to get ESC, ALT, etc.. handling. 
            return base.ProcessCmdKey(ref m, keyData); 
        }
 

        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")] // 'charCode' matches control.cs 
        protected internal override bool ProcessMnemonic(char charCode) {
             // no need to check IsMnemonic, toolstrip.ProcessMnemonic checks this already. 
             if (HasDropDownItems) { 
 				 Select();
                 ShowDropDown(); 
                 DropDown.SelectNextToolStripItem(null, /*forward=*/true);
                 return true;
             }
 
             return base.ProcessMnemonic(charCode);
        } 
 
        /// 
        ///  overridden here so we scooch over when we're in the ToolStripDropDownMenu 
        internal protected override void SetBounds(Rectangle rect) {

            ToolStripMenuItemInternalLayout internalLayout = InternalLayout as ToolStripMenuItemInternalLayout;
            if (internalLayout != null && internalLayout.UseMenuLayout) { 
               ToolStripDropDownMenu dropDownMenu = Owner as ToolStripDropDownMenu;
 
               // Scooch over by the padding amount.  The padding is added to 
               // the ToolStripDropDownMenu to keep the non-menu item riffraff
               // aligned to the text rectangle. When flow layout comes through to set our position 
               // via IArrangedElement DEFY IT!
               if (dropDownMenu != null) {
                    rect.X -= dropDownMenu.Padding.Left;
                    rect.X = Math.Max(rect.X,0); 
               }
            } 
            base.SetBounds(rect); 
        }
 
        ///  this is to support routing to native menu commands 
        internal void SetNativeTargetWindow(IWin32Window window) {
            targetWindowHandle = Control.GetSafeHandle(window);
        } 

        ///  this is to support routing to native menu commands  
        internal void SetNativeTargetMenu(IntPtr hMenu) { 
            nativeMenuHandle = hMenu;
        } 
        internal static string ShortcutToText(Keys shortcutKeys, string shortcutKeyDisplayString) {
            if (!string.IsNullOrEmpty(shortcutKeyDisplayString)) {
                return shortcutKeyDisplayString;
            } 
            else if (shortcutKeys == Keys.None) {
                return String.Empty; 
            } 
            else {
                return TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString(shortcutKeys); 
            }
        }

        ///  
        /// An implementation of AccessibleChild for use with ToolStripItems
        ///  
        [System.Runtime.InteropServices.ComVisible(true)] 
        internal class ToolStripMenuItemAccessibleObject : ToolStripDropDownItemAccessibleObject {
            private ToolStripMenuItem ownerItem = null; 

            public ToolStripMenuItemAccessibleObject(ToolStripMenuItem ownerItem) : base(ownerItem) {
              this.ownerItem = ownerItem;
            } 

 
            public override AccessibleStates State { 
                get {
                  if (ownerItem.Enabled ) { 
                      AccessibleStates state = base.State;

                      if ((state & AccessibleStates.Pressed) == AccessibleStates.Pressed){
                         // for some reason menu items are never "pressed". 
                         state &= ~AccessibleStates.Pressed;
                      } 
 
                      if (ownerItem.Checked) {
                         state |= AccessibleStates.Checked; 
                      }
                      return state;
                  }
                  return base.State; 
                }
            } 
 
        }
 
    }


    internal class MenuTimer { 

        private System.Windows.Forms.Timer autoMenuExpandTimer                          = new System.Windows.Forms.Timer(); 
 
        // consider - weak reference?
        private ToolStripMenuItem currentItem = null; 
        private ToolStripMenuItem fromItem = null;
        private bool inTransition = false;

        private int quickShow = 1; 

        private int slowShow; 
 
        public MenuTimer() {
            // MenuShowDelay can be set to 0.  In this case, set to something low so it's inperceptable. 
            autoMenuExpandTimer.Tick        += new EventHandler(OnTick);

            // since MenuShowDelay is registry tweakable we've gotta make sure we've got some sort
            // of interval 
            slowShow =  Math.Max(quickShow, SystemInformation.MenuShowDelay);
 
        } 
        // the current item to autoexpand.
        private ToolStripMenuItem CurrentItem { 
            get {
                return currentItem;
            }
            set{ 
                Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose && currentItem != value, "[MenuTimer.CurrentItem] changed: " + ((value == null) ? "null" : value.ToString()));
                currentItem = value; 
            } 
        }
        public bool InTransition { 
            get { return inTransition; }
            set { inTransition = value; }
        }
 
        public void Start(ToolStripMenuItem item) {
            if (InTransition) { 
                return; 
            }
            StartCore(item); 
        }

        private void StartCore(ToolStripMenuItem item) {
             if (item != CurrentItem) { 
                Cancel(CurrentItem);
            } 
            CurrentItem = item; 
            if (item != null) {
                CurrentItem = item; 
                autoMenuExpandTimer.Interval = item.IsOnDropDown ? slowShow : quickShow;
                autoMenuExpandTimer.Enabled = true;
            }
         } 

        public void Transition(ToolStripMenuItem fromItem, ToolStripMenuItem toItem) { 
            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[MenuTimer.Transition] transitioning items " + fromItem.ToString() + " " + toItem.ToString()); 

            if (toItem == null && InTransition) { 
                Cancel();
                // in this case we're likely to have hit an item that's not a menu item
                // or nothing is selected.
                EndTransition(/*forceClose*/ true); 
                return;
            } 
 
            if (this.fromItem != fromItem) {
              this.fromItem = fromItem; 
              CancelCore();
              StartCore(toItem);
            }
            // set up the current item to be the toItem so it will be auto expanded when complete. 
            CurrentItem = toItem;
            InTransition = true; 
 
        }
 

        public void Cancel() {
            if (InTransition) {
                return; 
            }
            CancelCore(); 
 
        }
        /// cancels if and only if this item was the one that 
        ///         requested the timer
        ///
        public void Cancel(ToolStripMenuItem item) {
            if (InTransition) { 
                return;
            } 
            if (item == CurrentItem) { 
                CancelCore();
           } 
        }

        private void CancelCore() {
            autoMenuExpandTimer.Enabled = false; 
            CurrentItem = null;
        } 
        private void EndTransition(bool forceClose) { 
            ToolStripMenuItem lastSelected = fromItem;
            fromItem = null; // immediately clear BEFORE we call user code. 
            if (InTransition) {
                InTransition = false;

                // we should roolup if the current item has changed and is selected. 
                bool rollup = forceClose || (CurrentItem != null && CurrentItem != lastSelected && CurrentItem.Selected);
                if (rollup && lastSelected != null && lastSelected.HasDropDownItems) { 
                    lastSelected.HideDropDown(); 
                }
 
            }

        }
        internal void HandleToolStripMouseLeave(ToolStrip toolStrip) { 
            if (InTransition && toolStrip == fromItem.ParentInternal) {
                // restore the selection back to CurrentItem. 
                // we're about to fall off the edge of the toolstrip, something should be selected 
                // at all times while we're InTransition mode - otherwise it looks really funny
                // to have an auto expanded item 
                if (CurrentItem != null) {
                    CurrentItem.Select();
                }
            } 
            else {
 
                // because we've split up selected/pressed, we need to make sure 
                // that onmouseleave we make sure there's a selected menu item.
                if (toolStrip.IsDropDown && toolStrip.ActiveDropDowns.Count > 0) { 
                    ToolStripDropDown dropDown = toolStrip.ActiveDropDowns[0] as ToolStripDropDown;

                    ToolStripMenuItem menuItem = (dropDown == null) ? null : dropDown.OwnerItem as ToolStripMenuItem;
                    if (menuItem != null && menuItem.Pressed) { 
                        menuItem.Select();
                    } 
                } 
            }
        } 

        private void OnTick(object sender, EventArgs e) {
            autoMenuExpandTimer.Enabled = false;
 
            if (CurrentItem == null) {
                return; 
            } 
            EndTransition(/*forceClose*/false);
            if (CurrentItem != null && !CurrentItem.IsDisposed &&  CurrentItem.Selected && ToolStripManager.ModalMenuFilter.InMenuMode) { 
                Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[MenuTimer.OnTick] calling OnMenuAutoExpand");
                CurrentItem.OnMenuAutoExpand();
            }
        } 

 
    } 

    internal class ToolStripMenuItemInternalLayout : ToolStripItemInternalLayout { 
        private ToolStripMenuItem ownerItem;

        public ToolStripMenuItemInternalLayout(ToolStripMenuItem ownerItem) : base(ownerItem) {
            this.ownerItem = ownerItem; 
        }
 
        public bool ShowCheckMargin { 
            get{
                ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                if (menu != null) {
                    return menu.ShowCheckMargin;
                }
                return false; 
            }
        } 
        public bool ShowImageMargin { 
            get{
                ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                if (menu != null) {
                    return menu.ShowImageMargin;
                }
                return false; 
            }
        } 
 
        public bool PaintCheck {
            get { 
                return ShowCheckMargin || ShowImageMargin;
            }
        }
 
        public bool PaintImage {
            get { 
                return ShowImageMargin; 
            }
        } 
        public  Rectangle ArrowRectangle {
           get {
               if (UseMenuLayout) {
                   ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                   if (menu != null) {
                        // since menuItem.Padding isnt taken into consideration, we've got to recalc the centering of 
                        // the arrow rect per item 
                        Rectangle arrowRect = menu.ArrowRectangle;
                        arrowRect.Y = LayoutUtils.VAlign(arrowRect.Size, ownerItem.ClientBounds, ContentAlignment.MiddleCenter).Y; 
                        return arrowRect;
                   }
               }
               return Rectangle.Empty; 
           }
        } 
        public Rectangle CheckRectangle { 
            get {
                 if (UseMenuLayout) { 
                     ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu;
                     if (menu != null) {
                         Rectangle checkRectangle = menu.CheckRectangle;
                         if (ownerItem.CheckedImage != null) { 
                             int imageHeight = ownerItem.CheckedImage.Height;
                             // make sure we're vertically centered 
                             checkRectangle.Y += (checkRectangle.Height - imageHeight)/2; 
                             checkRectangle.Height = imageHeight;
                             return checkRectangle; 
                         }
                     }
                 }
                 return Rectangle.Empty; 
            }
        } 
        public override Rectangle ImageRectangle { 
            get {
                if (UseMenuLayout) { 
                    ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu;
                    if (menu != null) {

                        // since menuItem.Padding isnt taken into consideration, we've got to recalc the centering of 
                        // the image rect per item
                        Rectangle imageRect = menu.ImageRectangle; 
                        if (ownerItem.ImageScaling == ToolStripItemImageScaling.SizeToFit) { 
                            imageRect.Size = menu.ImageScalingSize;
                        } 
                        else {
                            //If we don't have an image, use the CheckedImage
                            Image image = ownerItem.Image ?? ownerItem.CheckedImage;
                            imageRect.Size = image.Size; 
                        }
                        imageRect.Y = LayoutUtils.VAlign(imageRect.Size, ownerItem.ClientBounds, ContentAlignment.MiddleCenter).Y; 
                        return imageRect; 
                    }
                } 
                return base.ImageRectangle;
            }
        }
 
        public override Rectangle TextRectangle {
            get { 
                if (UseMenuLayout) { 
                    ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu;
                    if (menu != null) { 
                        return menu.TextRectangle;
                    }
                }
                return base.TextRectangle; 
            }
        } 
 
        public bool UseMenuLayout {
            get { 
                return  ownerItem.Owner is ToolStripDropDownMenu;
            }
        }
 
        public override Size GetPreferredSize(Size constrainingSize) {
            if (UseMenuLayout) { 
                ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                if (menu != null) {
                    return menu.MaxItemSize; 
                }
            }
            return base.GetPreferredSize(constrainingSize);
        } 
    }
 
 } 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Windows.Forms {
    using System; 
    using System.Collections; 
    using System.ComponentModel;
    using System.Drawing; 
    using Microsoft.Win32;
    using System.Drawing.Imaging;
    using System.Threading;
    using System.Diagnostics; 
    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Forms.Layout; 
    using System.Security; 
    using System.Security.Permissions;
    using System.Runtime.InteropServices; 
    using System.ComponentModel.Design.Serialization;
    using System.Windows.Forms.Design;
    using System.Globalization;
    using System.Windows.Forms.Internal; 
    using System.Runtime.Versioning;
 
    ///  
    /// 
    /// ToolStripMenuItem 
    /// 
    [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.MenuStrip | ToolStripItemDesignerAvailability.ContextMenuStrip)]
    [DesignerSerializer("System.Windows.Forms.Design.ToolStripMenuItemCodeDomSerializer, " + AssemblyRef.SystemDesign, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + AssemblyRef.SystemDesign)]
    public class ToolStripMenuItem : ToolStripDropDownItem { 

        private static MenuTimer menuTimer                             = new MenuTimer(); 
 
        private static readonly int PropShortcutKeys                   = PropertyStore.CreateKey();
        private static readonly int PropCheckState                     = PropertyStore.CreateKey(); 
        private static readonly int PropMdiForm                        = PropertyStore.CreateKey();

        private bool checkOnClick                                      = false;
        private bool showShortcutKeys                                  = true; 
        private ToolStrip lastOwner                                    = null;
 
        // SUPPORT for mapping NATIVE menu commands to ToolStripMenuItems ----- 
        // corresponds to wID in MENUITEMINFO structure
        private int     nativeMenuCommandID                               = -1; 
        private IntPtr  targetWindowHandle                                = IntPtr.Zero;
        private IntPtr  nativeMenuHandle                                  = IntPtr.Zero;

        // Keep checked images shared between menu items, but per thread so we dont have locking issues in GDI+ 
        [ThreadStatic]
        private static Image indeterminateCheckedImage; 
 
        [ThreadStatic]
        private static Image checkedImage; 

        private string shortcutKeyDisplayString;
        private string cachedShortcutText;
        private Size cachedShortcutSize = Size.Empty; 

 
        private byte openMouseId = 0; 

        private static readonly object EventCheckedChanged = new object(); 
        private static readonly object EventCheckStateChanged = new object();

        /// 
        public ToolStripMenuItem() : base() { 
            Initialize(); // all additional work should be done in Initialize
        } 
        public ToolStripMenuItem(string text):base(text,null,(EventHandler)null) { 
            Initialize();
        } 
        public ToolStripMenuItem(Image image):base(null,image,(EventHandler)null) {
            Initialize();
        }
        public ToolStripMenuItem(string text, Image image):base(text,image,(EventHandler)null) { 
            Initialize();
        } 
        public ToolStripMenuItem(string text, Image image, EventHandler onClick):base(text,image,onClick) { 
            Initialize();
        } 
        public ToolStripMenuItem(string text, Image image, EventHandler onClick, string name) : base(text,image,onClick, name){
            Initialize();
        }
        public ToolStripMenuItem(string text, Image image, params ToolStripItem[] dropDownItems):base(text,image,dropDownItems) { 
            Initialize();
        } 
        public ToolStripMenuItem(string text, Image image, EventHandler onClick, Keys shortcutKeys):base(text,image,onClick) { 
            Initialize();
            this.ShortcutKeys = shortcutKeys; 
        }
        internal ToolStripMenuItem(Form mdiForm) {
            Initialize();
            Properties.SetObject(PropMdiForm,mdiForm); 
        }
 
        ///  this constructor is only used when we're trying to 
        ///          mimic a native menu like the system menu.  In that case
        ///          we've got to go ahead and collect the command id and the 
        ///          target window to send WM_COMMAND/WM_SYSCOMMAND messages to.
        /// 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        internal ToolStripMenuItem(IntPtr hMenu, int nativeMenuCommandId, IWin32Window targetWindow) { 
            Initialize();
            this.Overflow                   = ToolStripItemOverflow.Never; 
            this.nativeMenuCommandID        = nativeMenuCommandId; 
            this.targetWindowHandle         = Control.GetSafeHandle(targetWindow);
            this.nativeMenuHandle           = hMenu; 

            // Since fetching the image and the text is an awful lot of work
            // we're going to just cache it and assume the native stuff
            // doesnt update. 
            // we'll only live-update enabled.
            // if this becomes a problem we can override Image and Text properties 
            // to live-return the results. 

            // fetch image 
            this.Image = GetNativeMenuItemImage();
            this.ImageScaling = ToolStripItemImageScaling.None;

            // fetch text 
            string text = GetNativeMenuItemTextAndShortcut();
 
            // the shortcut is tab separated from the item text. 
            if (text != null) {
                // separate out the two fields. 
                string[] textFields = text.Split('\t');

                if (textFields.Length >= 1){
                    this.Text = textFields[0]; 
                }
 
                if (textFields.Length >= 2) { 
                    // VSWhidbey 448242: We dont care about the shortcut here, the OS is going to
                    // handle it for us by sending a WM_(SYS)COMMAND during TranslateAcellerator 
                    // Just display whatever the OS would have.
                    this.ShowShortcutKeys = true;
                    this.ShortcutKeyDisplayString = textFields[1];
                } 
            }
        } 
 
        internal override void AutoHide(ToolStripItem otherItemBeingSelected) {
            if (IsOnDropDown) { 
                MenuTimer.Transition(this,otherItemBeingSelected as ToolStripMenuItem);
            }
            else {
                base.AutoHide(otherItemBeingSelected); 
            }
        } 
        private void ClearShortcutCache() { 
            cachedShortcutSize = Size.Empty;
            cachedShortcutText = null; 
        }

        /// 
        protected override ToolStripDropDown CreateDefaultDropDown() { 
            // AutoGenerate a Winbar DropDown - set the property so we hook events
             return new ToolStripDropDownMenu(this, true); 
        } 

        internal override ToolStripItemInternalLayout CreateInternalLayout() { 
              return new ToolStripMenuItemInternalLayout(this);
        }

        [EditorBrowsable(EditorBrowsableState.Advanced)] 
        protected override AccessibleObject CreateAccessibilityInstance() {
            return new ToolStripMenuItemAccessibleObject(this); 
        } 

        private void Initialize() { 
            this.Overflow                   = ToolStripItemOverflow.Never;
            this.MouseDownAndUpMustBeInSameItem = false;
            this.SupportsDisabledHotTracking = true;
        } 

        ///  
        ///  
        /// Deriving classes can override this to configure a default size for their control.
        /// This is more efficient than setting the size in the control's constructor. 
        /// 
        protected override Size DefaultSize {
            get {
                return new Size(32, 19); 
            }
        } 
 

        ///  
        protected internal override Padding DefaultMargin {
            get {
                 return Padding.Empty;
            } 
        }
        ///  
        protected override Padding DefaultPadding { 
            get {
                if (IsOnDropDown) { 
                    return new Padding(0, 1, 0, 1);
                }
                else {
                    return new Padding(4, 0, 4, 0); 
                }
            } 
        } 

 
        public override bool Enabled {
           get{
                if (nativeMenuCommandID != -1) {
                    // if we're based off a native menu item, 
                    // we need to ask it if it's enabled.
                    if (base.Enabled && nativeMenuHandle != IntPtr.Zero && targetWindowHandle != IntPtr.Zero) { 
                        return GetNativeMenuItemEnabled(); 
                    }
                    return false; 
                }
                else {
                    return base.Enabled;
                } 
           }
           set { 
                base.Enabled = value; 
           }
        } 

        /// 
        /// 
        ///  
        /// Gets or sets a value indicating whether the item is checked.
        ///  
        ///  
        [
        Bindable(true), 
        DefaultValue(false),
        SRCategory(SR.CatAppearance),
        RefreshProperties(RefreshProperties.All),
        SRDescription(SR.CheckBoxCheckedDescr) 
        ]
        public bool Checked { 
            get { 
                return CheckState != CheckState.Unchecked;
            } 

            set {
                if (value != Checked) {
                    CheckState = value ? CheckState.Checked : CheckState.Unchecked; 
                    InvokePaint();
                } 
            } 
        }
 

        /// 
        /// Keeps a shared copy of the checked image between all menu items
        /// Fishes out the appropriate one based on CheckState. 
        /// 
        internal Image CheckedImage { 
            [ResourceExposure(ResourceScope.Machine)] 
            [ResourceConsumption(ResourceScope.Machine)]
            get { 
                CheckState checkedState = CheckState;

                if (checkedState == CheckState.Indeterminate) {
                    if (indeterminateCheckedImage == null) { 
                        Bitmap indeterminateCheckedBmp = new Bitmap(typeof(ToolStripMenuItem), "IndeterminateChecked.bmp");
                        if (indeterminateCheckedBmp != null) { 
                            // 
                            indeterminateCheckedBmp.MakeTransparent(indeterminateCheckedBmp.GetPixel(1,1));
                            indeterminateCheckedImage = indeterminateCheckedBmp; 
                        }
                    }
                    return indeterminateCheckedImage;
                } 
                else if (checkedState == CheckState.Checked)  {
                    if (checkedImage == null) { 
                        Bitmap checkedBmp = new Bitmap(typeof(ToolStripMenuItem), "Checked.bmp"); 
                         if (checkedBmp != null) {
                            // 
                            checkedBmp.MakeTransparent(checkedBmp.GetPixel(1,1));
                            checkedImage = checkedBmp;
                        }
                    } 
                    return checkedImage;
                } 
                return null; 

            } 
        }


         ///  
         [
         DefaultValue(false), 
         SRCategory(SR.CatBehavior), 
         SRDescription(SR.ToolStripButtonCheckOnClickDescr)
         ] 
         public bool CheckOnClick {
             get {
                 return checkOnClick;
             } 
             set {
                 checkOnClick = value; 
             } 
         }
 
        /// 
        /// 
        /// Gets
        /// or sets a value indicating whether the check box is checked. 
        /// 
        [ 
        Bindable(true), 
        SRCategory(SR.CatAppearance),
        DefaultValue(CheckState.Unchecked), 
        RefreshProperties(RefreshProperties.All),
        SRDescription(SR.CheckBoxCheckStateDescr)
        ]
        public CheckState CheckState { 
            get {
                bool found = false; 
                object checkState = Properties.GetInteger(PropCheckState, out found); 
                return (found) ? (CheckState)checkState : CheckState.Unchecked;
            } 

            set {
                //valid values are 0x0 to 0x2
                if (!ClientUtils.IsEnumValid(value, (int)value, (int)CheckState.Unchecked, (int)CheckState.Indeterminate)) 
                {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(CheckState)); 
                } 

                if (value != CheckState) { 
                    Properties.SetInteger(PropCheckState, (int)value);
                    OnCheckedChanged(EventArgs.Empty);
                    OnCheckStateChanged(EventArgs.Empty);
                } 
            }
        } 
 
        /// 
        ///  
        /// Occurs when the
        /// value of the 
        /// property changes.
        ///  
        [SRDescription(SR.CheckBoxOnCheckedChangedDescr)]
        public event EventHandler CheckedChanged { 
            add { 
                Events.AddHandler(EventCheckedChanged, value);
            } 
            remove {
                Events.RemoveHandler(EventCheckedChanged, value);
            }
        } 
        /// 
        ///  
        /// Occurs when the 
        /// value of the 
        /// property changes. 
        /// 
        [SRDescription(SR.CheckBoxOnCheckStateChangedDescr)]
        public event EventHandler CheckStateChanged {
            add { 
                Events.AddHandler(EventCheckStateChanged, value);
            } 
            remove { 
                Events.RemoveHandler(EventCheckStateChanged, value);
            } 
        }


        ///  
        /// 
        /// Specifies whether or not the item is glued to the winbar or overflow or 
        /// can float between the two. 
        /// 
        [ 
        DefaultValue(ToolStripItemOverflow.Never),
        SRDescription(SR.ToolStripItemOverflowDescr),
        SRCategory(SR.CatLayout)
     	] 
        public new ToolStripItemOverflow Overflow {
            get { 
                return base.Overflow; 
            }
            set { 
                base.Overflow = value;
            }
        }
 
        /// 
        ///  
        ///  
        /// Gets or sets the shortcut keys associated with the menu
        /// item. 
        /// 
        /// 
        [
        Localizable(true), 
        DefaultValue(Keys.None),
        SRDescription(SR.MenuItemShortCutDescr) 
        ] 
        public Keys ShortcutKeys {
            get { 
                bool found = false;
                object shortcutKeys = Properties.GetInteger(PropShortcutKeys, out found );
                return (found) ? (Keys)shortcutKeys : Keys.None;
            } 
            set {
                if ((value != Keys.None) && !ToolStripManager.IsValidShortcut(value)){ 
                    // prevent use of alt, ctrl, shift modifiers with no key code. 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(Keys));
                } 
                Keys originalShortcut = ShortcutKeys;
                if (originalShortcut != value) {
                    ClearShortcutCache();
                    ToolStrip owner = this.Owner; 
                    if (owner != null) {
                        // add to the shortcut caching system. 
                        if (originalShortcut != Keys.None) { 
                            owner.Shortcuts.Remove(originalShortcut);
                        } 
                        if (owner.Shortcuts.Contains(value)) {
                            // last one in wins.
                            owner.Shortcuts[value] = this;
                        } 
                        else {
                            owner.Shortcuts.Add(value, this); 
                        } 
                    }
                    Properties.SetInteger(PropShortcutKeys, (int)value); 

                    if (ShowShortcutKeys && IsOnDropDown) {
                        ToolStripDropDownMenu parent = GetCurrentParentDropDown() as ToolStripDropDownMenu;
                        if (parent != null) { 
                            LayoutTransaction.DoLayout(this.ParentInternal, this, "ShortcutKeys");
                            parent.AdjustSize(); 
                        } 
                    }
                } 
            }

        }
 
        [
        SRDescription(SR.ToolStripMenuItemShortcutKeyDisplayStringDescr), 
        SRCategory(SR.CatAppearance), 
        DefaultValue(null),
        Localizable(true) 
        ]
        public string ShortcutKeyDisplayString {
            get {
                return shortcutKeyDisplayString; 
            }
            set { 
                if (shortcutKeyDisplayString != value) { 
                    shortcutKeyDisplayString = value;
                    ClearShortcutCache(); 
                    if (ShowShortcutKeys) {
                        ToolStripDropDown parent = this.ParentInternal as ToolStripDropDown;
                        if (parent != null) {
                            LayoutTransaction.DoLayout(parent, this, "ShortcutKeyDisplayString"); 
                            parent.AdjustSize();
                        } 
                    } 
                }
            } 
        }

        /// 
        ///  
        /// 
        /// Gets or sets a value that indicates whether the shortcut 
        /// keys that are assocaited 
        /// with the menu item are displayed next to the menu item
        /// caption. 
        /// 
        /// 
        [
        DefaultValue(true), 
        Localizable(true),
        SRDescription(SR.MenuItemShowShortCutDescr) 
        ] 
        public bool ShowShortcutKeys {
            get { 
                return showShortcutKeys;
            }
            set {
                if (value != showShortcutKeys) { 
                   ClearShortcutCache();
                   showShortcutKeys = value; 
                   ToolStripDropDown parent = this.ParentInternal as ToolStripDropDown; 
                   if (parent != null) {
                        LayoutTransaction.DoLayout(parent, this, "ShortcutKeys"); 
                        parent.AdjustSize();

                    }
                } 
            }
        } 
 

        ///  
        /// An item is toplevel if it is parented to anything other than a ToolStripDropDownMenu
        /// This implies that a ToolStripMenuItem in an overflow IS a toplevel item
        /// 
        internal bool IsTopLevel { 
            get {
                return (this.ParentInternal as ToolStripDropDown == null); 
            } 
        }
 
        [Browsable(false)]
        public bool IsMdiWindowListEntry {
            get{
                return MdiForm != null; 
            }
        } 
 
        internal static MenuTimer MenuTimer {
            get { 
                return menuTimer;
            }
        }
 

        ///  Tag property for internal use  
        internal Form MdiForm { 
            get {
                if (Properties.ContainsObject(PropMdiForm)) { 
                    return Properties.GetObject(PropMdiForm) as Form;
                }
                return null;
 
            }
        } 
 
        internal ToolStripMenuItem Clone() {
 
            // dirt simple clone - just properties, no subitems

            ToolStripMenuItem menuItem = new ToolStripMenuItem();
            menuItem.Events.AddHandlers(this.Events); 

            menuItem.AccessibleName = this.AccessibleName; 
            menuItem.AccessibleRole = this.AccessibleRole; 
            menuItem.Alignment = this.Alignment;
            menuItem.AllowDrop = this.AllowDrop; 
            menuItem.Anchor = this.Anchor;
            menuItem.AutoSize = this.AutoSize;
            menuItem.AutoToolTip = this.AutoToolTip;
            menuItem.BackColor = this.BackColor; 
            menuItem.BackgroundImage = this.BackgroundImage;
            menuItem.BackgroundImageLayout = this.BackgroundImageLayout; 
            menuItem.Checked = this.Checked; 
            menuItem.CheckOnClick = this.CheckOnClick;
            menuItem.CheckState = this.CheckState; 
            menuItem.DisplayStyle = this.DisplayStyle;
            menuItem.Dock = this.Dock;
            menuItem.DoubleClickEnabled = this.DoubleClickEnabled;
            menuItem.Enabled = this.Enabled; 
            menuItem.Font = this.Font;
            menuItem.ForeColor = this.ForeColor; 
            menuItem.Image = this.Image; 
            menuItem.ImageAlign = this.ImageAlign;
            menuItem.ImageScaling = this.ImageScaling; 
            menuItem.ImageTransparentColor = this.ImageTransparentColor;
            menuItem.Margin = this.Margin;
            menuItem.MergeAction = this.MergeAction;
            menuItem.MergeIndex = this.MergeIndex; 
            menuItem.Name = this.Name;
            menuItem.Overflow = this.Overflow; 
            menuItem.Padding = this.Padding; 
            menuItem.RightToLeft= this.RightToLeft;
 
            // No settings support for cloned items.
            // menuItem.SaveSettings= this.SaveSettings;
            // menuItem.SettingsKey = this.SettingsKey;
 
            menuItem.ShortcutKeys = this.ShortcutKeys;
            menuItem.ShowShortcutKeys = this.ShowShortcutKeys; 
            menuItem.Tag = this.Tag; 
            menuItem.Text = this.Text;
            menuItem.TextAlign = this.TextAlign; 
            menuItem.TextDirection = this.TextDirection;
            menuItem.TextImageRelation = this.TextImageRelation;
            menuItem.ToolTipText = this.ToolTipText;
 
            // cant actually use "Visible" property as that returns whether or not the parent
            // is visible too.. instead use ParticipatesInLayout as this queries the actual state. 
            menuItem.Visible = ((IArrangedElement)this).ParticipatesInLayout; 

            if (!AutoSize) { 
                menuItem.Size = this.Size;
            }
            return menuItem;
       } 

        protected override void Dispose(bool disposing) { 
            if (disposing) { 
                if (lastOwner != null) {
                    Keys shortcut = this.ShortcutKeys; 
                    if (shortcut != Keys.None && lastOwner.Shortcuts.ContainsKey(shortcut)) {
                        lastOwner.Shortcuts.Remove(shortcut);
                    }
                    lastOwner = null; 
                    if (MdiForm != null) {
                        Properties.SetObject(PropMdiForm,null); 
                    } 

                } 
            }
            base.Dispose(disposing);
        }
 
        private bool GetNativeMenuItemEnabled() {
            if (nativeMenuCommandID == -1 || nativeMenuHandle == IntPtr.Zero) { 
                Debug.Fail("why were we called to fetch native menu item info with nothing assigned?"); 
                return false;
            } 
            NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW();
            info.cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T_RW));
            info.fMask = NativeMethods.MIIM_STATE;
            info.fType = NativeMethods.MIIM_STATE; 
            info.wID = nativeMenuCommandID;
            UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/ false, info); 
 
            return ((info.fState & NativeMethods.MFS_DISABLED) == 0);
        } 

        // returns text and shortcut separated by tab.
        private string GetNativeMenuItemTextAndShortcut() {
 
            if (nativeMenuCommandID == -1 || nativeMenuHandle == IntPtr.Zero) {
                Debug.Fail("why were we called to fetch native menu item info with nothing assigned?"); 
                return null; 
            }
            string text = null; 

            // fetch the string length
            NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW();
            info.fMask = NativeMethods.MIIM_STRING; 
            info.fType = NativeMethods.MIIM_STRING;
            info.wID = nativeMenuCommandID; 
            info.dwTypeData = IntPtr.Zero; 
            UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/  false, info);
 
            if (info.cch > 0) {
                // fetch the string
                info.cch += 1;  // according to MSDN we need to increment the count we receive by 1.
                info.wID = nativeMenuCommandID; 
                IntPtr allocatedStringBuffer = Marshal.AllocCoTaskMem(info.cch * Marshal.SystemDefaultCharSize);
                info.dwTypeData = allocatedStringBuffer; 
 

                try { 
                    UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/  false, info);

                    // convert the string into managed data.
                	if (info.dwTypeData != IntPtr.Zero){ 
                        // we have to use PtrToStringAuto as we can't use Marshal.SizeOf to determine
                        // the size of the struct with a StringBuilder member. 
                        text = Marshal.PtrToStringAuto(info.dwTypeData, info.cch); 
                    }
                } 
                finally {
                   if (allocatedStringBuffer != IntPtr.Zero) {
                        // use our local instead of the info structure member *just* in case windows decides to clobber over it.
                        // we want to be sure to deallocate the memory we know we allocated. 
                        Marshal.FreeCoTaskMem(allocatedStringBuffer);
                    } 
                } 
            }
            return text; 
        }

        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine | ResourceScope.Process, ResourceScope.Machine | ResourceScope.Process)] 
        private Image GetNativeMenuItemImage(){
 
            if (nativeMenuCommandID == -1 || nativeMenuHandle == IntPtr.Zero) { 
                Debug.Fail("why were we called to fetch native menu item info with nothing assigned?");
                return null; 
            }

            NativeMethods.MENUITEMINFO_T_RW info = new NativeMethods.MENUITEMINFO_T_RW();
            info.fMask = NativeMethods.MIIM_BITMAP; 
            info.fType = NativeMethods.MIIM_BITMAP;
            info.wID = nativeMenuCommandID; 
            UnsafeNativeMethods.GetMenuItemInfo(new HandleRef(this, nativeMenuHandle), nativeMenuCommandID, /*fByPosition instead of ID=*/ false, info); 

            if (info.hbmpItem != IntPtr.Zero && info.hbmpItem.ToInt32() > NativeMethods.HBMMENU_POPUP_MINIMIZE) { 
                return Bitmap.FromHbitmap(info.hbmpItem);
            }
            else {
                // its a system defined bitmap 
                int buttonToUse = -1;
 
                switch (info.hbmpItem.ToInt32()) { 
                    case NativeMethods.HBMMENU_MBAR_CLOSE:
                    case NativeMethods.HBMMENU_MBAR_CLOSE_D: 
                    case NativeMethods.HBMMENU_POPUP_CLOSE:
                        buttonToUse = (int)CaptionButton.Close;
                        break;
 
                    case NativeMethods.HBMMENU_MBAR_MINIMIZE:
                    case NativeMethods.HBMMENU_MBAR_MINIMIZE_D: 
                    case NativeMethods.HBMMENU_POPUP_MINIMIZE: 
                        buttonToUse = (int)CaptionButton.Minimize;
                        break; 

                    case NativeMethods.HBMMENU_MBAR_RESTORE:
                    case NativeMethods.HBMMENU_POPUP_RESTORE:
                        buttonToUse = (int)CaptionButton.Restore; 
                        break;
 
                    case NativeMethods.HBMMENU_POPUP_MAXIMIZE: 
                        buttonToUse = (int)CaptionButton.Maximize;
                        break; 

                    case NativeMethods.HBMMENU_SYSTEM:
                        //
                    case NativeMethods.HBMMENU_CALLBACK: 
                        // owner draw not supported
                        default: 
                        break; 
                }
                if (buttonToUse > -1) { 

                    // we've mapped to a system defined bitmap we know how to draw
                    Bitmap image = new Bitmap(16, 16);
 
                    using (Graphics g = Graphics.FromImage(image)) {
                        ControlPaint.DrawCaptionButton(g, new Rectangle(Point.Empty, image.Size), (CaptionButton)buttonToUse, ButtonState.Flat); 
                        g.DrawRectangle(SystemPens.Control, 0, 0, image.Width - 1, image.Height - 1); 
                    }
 
                    image.MakeTransparent(SystemColors.Control);
                    return image;
                }
            } 
            return null;
        } 
 

        internal Size GetShortcutTextSize() { 
             if (!ShowShortcutKeys) {
                return Size.Empty;
             }
             string shortcutString = GetShortcutText(); 
             if (string.IsNullOrEmpty(shortcutString)) {
                return Size.Empty; 
             } 
             else if (cachedShortcutSize == Size.Empty) {
                cachedShortcutSize = TextRenderer.MeasureText(shortcutString, Font); 
             }
             return cachedShortcutSize;
        }
 
        private string GetShortcutText() {
            if (cachedShortcutText == null) { 
                cachedShortcutText = ShortcutToText(this.ShortcutKeys, this.ShortcutKeyDisplayString); 
            }
            return cachedShortcutText; 
        }

        internal void HandleAutoExpansion() {
            if (Enabled && ParentInternal != null && ParentInternal.MenuAutoExpand && HasDropDownItems) { 
                ShowDropDown();
                DropDown.SelectNextToolStripItem(null, /*forward=*/true); 
            } 
        }
 
        /// 
        protected override void OnClick(EventArgs e) {
            if (checkOnClick) {
                this.Checked = !this.Checked; 
            }
            base.OnClick(e); 
            if (nativeMenuCommandID != -1) { 
                // fire off the appropriate native handler by posting a message to the window target.
                if ((nativeMenuCommandID & 0xF000) != 0) { 
                    // These are system menu items like Minimize, Maximize, Restore, Resize, Move, Close.

                    // use PostMessage instead of SendMessage so that the DefWndProc can appropriately handle
                    // the system message... if we use SendMessage the dismissal of our window 
                    // breaks things like the modal sizing loop.
                    UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), NativeMethods.WM_SYSCOMMAND,nativeMenuCommandID, 0); 
                } 
                else {
                    // These are user added items like ".Net Window..." 

                    // be consistent with sending a WM_SYSCOMMAND, use POST not SEND.
                    UnsafeNativeMethods.PostMessage( new HandleRef(this, targetWindowHandle), NativeMethods.WM_COMMAND, nativeMenuCommandID, 0);
                } 
                this.Invalidate();
            } 
 
        }
 
        /// 
        /// 
        /// Raises the 
        /// event. 
        /// 
        protected virtual void OnCheckedChanged(EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventCheckedChanged]; 
            if (handler != null) handler(this,e);
        } 

        /// 
        /// 
        /// Raises the  event. 
        /// 
        protected virtual void OnCheckStateChanged(EventArgs e) { 
            AccessibilityNotifyClients(AccessibleEvents.StateChange); 
            EventHandler handler = (EventHandler)Events[EventCheckStateChanged];
            if (handler != null) handler(this,e); 
        }

        /// 
        protected override void OnDropDownHide(EventArgs e) { 

            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnDropDownHide] MenuTimer.Cancel called"); 
            MenuTimer.Cancel(this); 
            base.OnDropDownHide(e);
        } 

        protected override void OnDropDownShow(EventArgs e) {
            // if someone has beaten us to the punch by arrowing around
            // cancel the current menu timer. 
            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnDropDownShow] MenuTimer.Cancel called");
            MenuTimer.Cancel(this); 
            if (ParentInternal != null) { 
                ParentInternal.MenuAutoExpand = true;
            } 
            base.OnDropDownShow(e);
        }

        protected override void OnFontChanged(EventArgs e) { 
            ClearShortcutCache();
            base.OnFontChanged(e); 
        } 
        /// 
        internal void OnMenuAutoExpand() { 
            this.ShowDropDown();
        }

 
        /// 
        ///  
        protected override void OnMouseDown(MouseEventArgs e) { 

            // Opening should happen on mouse down 
            // we use a mouse down ID to ensure that the reshow

            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnMouseDown] MenuTimer.Cancel called");
            MenuTimer.Cancel(this); 
            OnMouseButtonStateChange(e, /*isMouseDown=*/true);
 
        } 

        protected override void OnMouseUp(MouseEventArgs e) { 
           OnMouseButtonStateChange(e, /*isMouseDown=*/false);
           base.OnMouseUp(e);
        }
 
        private void OnMouseButtonStateChange(MouseEventArgs e, bool isMouseDown) {
            bool showDropDown = true; 
            if (IsOnDropDown) { 
              ToolStripDropDown dropDown = GetCurrentParentDropDown() as ToolStripDropDown;
 
              // VSWhidbey 260536 - right click support for context menus.
              // used in ToolStripItem to determine whether to fire click OnMouseUp.
              SupportsRightClick = (dropDown.GetFirstDropDown() is ContextMenuStrip);
            } 
            else {
              showDropDown = !DropDown.Visible; 
              SupportsRightClick = false; 
            }
 
            if (e.Button == MouseButtons.Left ||
              (e.Button == MouseButtons.Right && SupportsRightClick)) {

                if (isMouseDown && showDropDown) { 
                    // opening should happen on mouse down.
                    Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID"); 
                    openMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId(); 
                    this.ShowDropDown(/*mousePush =*/true);
 
                }
                else if (!isMouseDown && !showDropDown) {
                    // closing should happen on mouse up.  ensure it's not the mouse
                    // up for the mouse down we opened with. 
                    Debug.Assert(ParentInternal != null, "Parent is null here, not going to get accurate ID");
                    byte closeMouseId = (ParentInternal == null) ? (byte)0: ParentInternal.GetMouseId(); 
                    int openedMouseID =openMouseId; 
                    if (closeMouseId != openedMouseID) {
                        openMouseId = 0;  // reset the mouse id, we should never get this value from toolstrip. 
                        ToolStripManager.ModalMenuFilter.CloseActiveDropDown(DropDown, ToolStripDropDownCloseReason.AppClicked);
                        Select();
                    }
 
                }
 
            } 
        }
 


        /// 
        ///  
        protected override void OnMouseEnter(EventArgs e) {
 
            Debug.Assert(this.ParentInternal != null, "Why is parent null"); 

            // If we are in a submenu pop down the submenu.		 
            if (this.ParentInternal != null && this.ParentInternal.MenuAutoExpand && Selected) {
                Debug.WriteLineIf(ToolStripItem.MouseDebugging.TraceVerbose, "received mouse enter - calling drop down");

                Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnMouseEnter] MenuTimer.Cancel / MenuTimer.Start called"); 

                MenuTimer.Cancel(this); 
                MenuTimer.Start(this); 

            } 
            base.OnMouseEnter(e);
        }

 
        /// 
        ///  
        protected override void OnMouseLeave(EventArgs e) { 
              Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[ToolStripMenuItem.OnMouseLeave] MenuTimer.Cancel called");
              MenuTimer.Cancel(this); 
              base.OnMouseLeave(e);
        }

        protected override void OnOwnerChanged(EventArgs e) { 

            Keys shortcut = this.ShortcutKeys; 
            if (shortcut != Keys.None) { 
                if (lastOwner != null) {
                    lastOwner.Shortcuts.Remove(shortcut); 
                }

                if (Owner != null) {
                   if (Owner.Shortcuts.Contains(shortcut)) { 
                        // last one in wins
                        Owner.Shortcuts[shortcut] = this; 
                   } 
                   else {
                        Owner.Shortcuts.Add(shortcut, this); 
                   }
                   lastOwner = Owner;
                }
            } 

            base.OnOwnerChanged(e); 
        } 

        ///  
        /// 
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {

            if (this.Owner != null) { 
                ToolStripRenderer renderer = this.Renderer;
                Graphics g = e.Graphics; 
                renderer.DrawMenuItemBackground(new ToolStripItemRenderEventArgs(g, this)); 

                Color textColor = SystemColors.MenuText; 
                if (IsForeColorSet) {
                    textColor =  this.ForeColor;
                }
                else if (!this.IsTopLevel || (ToolStripManager.VisualStylesEnabled)) { 
                    if (Selected || Pressed) {
                        textColor = SystemColors.HighlightText; 
                    } 
                    else {
                        textColor =  SystemColors.MenuText; 
                    }
                }

                bool rightToLeft = (RightToLeft == RightToLeft.Yes); 

                ToolStripMenuItemInternalLayout menuItemInternalLayout = this.InternalLayout as ToolStripMenuItemInternalLayout; 
                if (menuItemInternalLayout != null && menuItemInternalLayout.UseMenuLayout) { 

                    // Support for special DropDownMenu layout 
                    #if DEBUG_PAINT
                        g.DrawRectangle(Pens.Green, menuItemInternalLayout.TextRectangle);
                        g.DrawRectangle(Pens.HotPink, menuItemInternalLayout.ImageRectangle);
                        g.DrawRectangle(Pens.Black, menuItemInternalLayout.CheckRectangle); 
                        g.DrawRectangle(Pens.Red, menuItemInternalLayout.ArrowRectangle);
                        g.DrawRectangle(Pens.Blue, new Rectangle(Point.Empty, new Size(-1,-1) + this.Size)); 
                    #endif 
                    if (CheckState != CheckState.Unchecked && menuItemInternalLayout.PaintCheck) {
                        Rectangle checkRectangle = menuItemInternalLayout.CheckRectangle; 
                        if (!menuItemInternalLayout.ShowCheckMargin) {
                            checkRectangle =  menuItemInternalLayout.ImageRectangle;
                        }
                        if (checkRectangle.Width != 0) { 
                            renderer.DrawItemCheck(new ToolStripItemImageRenderEventArgs(g, this, CheckedImage, checkRectangle));
                        } 
                    } 

 
                   if ((DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) {

                        // render text AND shortcut
                        renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, this.Text, InternalLayout.TextRectangle, textColor, this.Font, (rightToLeft) ? ContentAlignment.MiddleRight : ContentAlignment.MiddleLeft)); 
                        bool showShortCut = ShowShortcutKeys;
                        if (!DesignMode){ 
                            showShortCut = showShortCut && !HasDropDownItems; 
                        }
 
                        if (showShortCut) {
                            renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, GetShortcutText(), InternalLayout.TextRectangle, textColor, this.Font, (rightToLeft) ? ContentAlignment.MiddleLeft : ContentAlignment.MiddleRight));
                        }
                   } 

                    if (HasDropDownItems) { 
 
                        ArrowDirection arrowDir = (rightToLeft) ? ArrowDirection.Left : ArrowDirection.Right;
                        Color arrowColor = (Selected ||Pressed) ? SystemColors.HighlightText : SystemColors.MenuText; 
                        arrowColor = (Enabled) ? arrowColor : SystemColors.ControlDark;
                        renderer.DrawArrow(new ToolStripArrowRenderEventArgs(g, this, menuItemInternalLayout.ArrowRectangle, arrowColor, arrowDir));
                    }
 
                    if (menuItemInternalLayout.PaintImage && (DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image && Image != null) {
                       renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, InternalLayout.ImageRectangle)); 
                    } 

                } 
                else {


                    // Toplevel item support, menu items hosted on a plain winbar dropdown 
                    if ((DisplayStyle & ToolStripItemDisplayStyle.Text) == ToolStripItemDisplayStyle.Text) {
                        renderer.DrawItemText(new ToolStripItemTextRenderEventArgs(g, this, this.Text, InternalLayout.TextRectangle, textColor, this.Font, InternalLayout.TextFormat)); 
                    } 

                    if ((DisplayStyle & ToolStripItemDisplayStyle.Image) == ToolStripItemDisplayStyle.Image && Image != null) { 
                       renderer.DrawItemImage(new ToolStripItemImageRenderEventArgs(g, this, InternalLayout.ImageRectangle));
                    }
                }
 

            } 
 
        }
 
        /// 
        /// 
        /// handle shortcut keys here.
        ///  
        [
        SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
        ] 
        protected internal override bool ProcessCmdKey(ref Message m, Keys keyData) {
 
            if (Enabled && ShortcutKeys == keyData && !HasDropDownItems) {
                FireEvent(ToolStripItemEventType.Click);
                return true;
            } 

            // call base here to get ESC, ALT, etc.. handling. 
            return base.ProcessCmdKey(ref m, keyData); 
        }
 

        /// 
        [UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters")] // 'charCode' matches control.cs 
        protected internal override bool ProcessMnemonic(char charCode) {
             // no need to check IsMnemonic, toolstrip.ProcessMnemonic checks this already. 
             if (HasDropDownItems) { 
 				 Select();
                 ShowDropDown(); 
                 DropDown.SelectNextToolStripItem(null, /*forward=*/true);
                 return true;
             }
 
             return base.ProcessMnemonic(charCode);
        } 
 
        /// 
        ///  overridden here so we scooch over when we're in the ToolStripDropDownMenu 
        internal protected override void SetBounds(Rectangle rect) {

            ToolStripMenuItemInternalLayout internalLayout = InternalLayout as ToolStripMenuItemInternalLayout;
            if (internalLayout != null && internalLayout.UseMenuLayout) { 
               ToolStripDropDownMenu dropDownMenu = Owner as ToolStripDropDownMenu;
 
               // Scooch over by the padding amount.  The padding is added to 
               // the ToolStripDropDownMenu to keep the non-menu item riffraff
               // aligned to the text rectangle. When flow layout comes through to set our position 
               // via IArrangedElement DEFY IT!
               if (dropDownMenu != null) {
                    rect.X -= dropDownMenu.Padding.Left;
                    rect.X = Math.Max(rect.X,0); 
               }
            } 
            base.SetBounds(rect); 
        }
 
        ///  this is to support routing to native menu commands 
        internal void SetNativeTargetWindow(IWin32Window window) {
            targetWindowHandle = Control.GetSafeHandle(window);
        } 

        ///  this is to support routing to native menu commands  
        internal void SetNativeTargetMenu(IntPtr hMenu) { 
            nativeMenuHandle = hMenu;
        } 
        internal static string ShortcutToText(Keys shortcutKeys, string shortcutKeyDisplayString) {
            if (!string.IsNullOrEmpty(shortcutKeyDisplayString)) {
                return shortcutKeyDisplayString;
            } 
            else if (shortcutKeys == Keys.None) {
                return String.Empty; 
            } 
            else {
                return TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString(shortcutKeys); 
            }
        }

        ///  
        /// An implementation of AccessibleChild for use with ToolStripItems
        ///  
        [System.Runtime.InteropServices.ComVisible(true)] 
        internal class ToolStripMenuItemAccessibleObject : ToolStripDropDownItemAccessibleObject {
            private ToolStripMenuItem ownerItem = null; 

            public ToolStripMenuItemAccessibleObject(ToolStripMenuItem ownerItem) : base(ownerItem) {
              this.ownerItem = ownerItem;
            } 

 
            public override AccessibleStates State { 
                get {
                  if (ownerItem.Enabled ) { 
                      AccessibleStates state = base.State;

                      if ((state & AccessibleStates.Pressed) == AccessibleStates.Pressed){
                         // for some reason menu items are never "pressed". 
                         state &= ~AccessibleStates.Pressed;
                      } 
 
                      if (ownerItem.Checked) {
                         state |= AccessibleStates.Checked; 
                      }
                      return state;
                  }
                  return base.State; 
                }
            } 
 
        }
 
    }


    internal class MenuTimer { 

        private System.Windows.Forms.Timer autoMenuExpandTimer                          = new System.Windows.Forms.Timer(); 
 
        // consider - weak reference?
        private ToolStripMenuItem currentItem = null; 
        private ToolStripMenuItem fromItem = null;
        private bool inTransition = false;

        private int quickShow = 1; 

        private int slowShow; 
 
        public MenuTimer() {
            // MenuShowDelay can be set to 0.  In this case, set to something low so it's inperceptable. 
            autoMenuExpandTimer.Tick        += new EventHandler(OnTick);

            // since MenuShowDelay is registry tweakable we've gotta make sure we've got some sort
            // of interval 
            slowShow =  Math.Max(quickShow, SystemInformation.MenuShowDelay);
 
        } 
        // the current item to autoexpand.
        private ToolStripMenuItem CurrentItem { 
            get {
                return currentItem;
            }
            set{ 
                Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose && currentItem != value, "[MenuTimer.CurrentItem] changed: " + ((value == null) ? "null" : value.ToString()));
                currentItem = value; 
            } 
        }
        public bool InTransition { 
            get { return inTransition; }
            set { inTransition = value; }
        }
 
        public void Start(ToolStripMenuItem item) {
            if (InTransition) { 
                return; 
            }
            StartCore(item); 
        }

        private void StartCore(ToolStripMenuItem item) {
             if (item != CurrentItem) { 
                Cancel(CurrentItem);
            } 
            CurrentItem = item; 
            if (item != null) {
                CurrentItem = item; 
                autoMenuExpandTimer.Interval = item.IsOnDropDown ? slowShow : quickShow;
                autoMenuExpandTimer.Enabled = true;
            }
         } 

        public void Transition(ToolStripMenuItem fromItem, ToolStripMenuItem toItem) { 
            Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[MenuTimer.Transition] transitioning items " + fromItem.ToString() + " " + toItem.ToString()); 

            if (toItem == null && InTransition) { 
                Cancel();
                // in this case we're likely to have hit an item that's not a menu item
                // or nothing is selected.
                EndTransition(/*forceClose*/ true); 
                return;
            } 
 
            if (this.fromItem != fromItem) {
              this.fromItem = fromItem; 
              CancelCore();
              StartCore(toItem);
            }
            // set up the current item to be the toItem so it will be auto expanded when complete. 
            CurrentItem = toItem;
            InTransition = true; 
 
        }
 

        public void Cancel() {
            if (InTransition) {
                return; 
            }
            CancelCore(); 
 
        }
        /// cancels if and only if this item was the one that 
        ///         requested the timer
        ///
        public void Cancel(ToolStripMenuItem item) {
            if (InTransition) { 
                return;
            } 
            if (item == CurrentItem) { 
                CancelCore();
           } 
        }

        private void CancelCore() {
            autoMenuExpandTimer.Enabled = false; 
            CurrentItem = null;
        } 
        private void EndTransition(bool forceClose) { 
            ToolStripMenuItem lastSelected = fromItem;
            fromItem = null; // immediately clear BEFORE we call user code. 
            if (InTransition) {
                InTransition = false;

                // we should roolup if the current item has changed and is selected. 
                bool rollup = forceClose || (CurrentItem != null && CurrentItem != lastSelected && CurrentItem.Selected);
                if (rollup && lastSelected != null && lastSelected.HasDropDownItems) { 
                    lastSelected.HideDropDown(); 
                }
 
            }

        }
        internal void HandleToolStripMouseLeave(ToolStrip toolStrip) { 
            if (InTransition && toolStrip == fromItem.ParentInternal) {
                // restore the selection back to CurrentItem. 
                // we're about to fall off the edge of the toolstrip, something should be selected 
                // at all times while we're InTransition mode - otherwise it looks really funny
                // to have an auto expanded item 
                if (CurrentItem != null) {
                    CurrentItem.Select();
                }
            } 
            else {
 
                // because we've split up selected/pressed, we need to make sure 
                // that onmouseleave we make sure there's a selected menu item.
                if (toolStrip.IsDropDown && toolStrip.ActiveDropDowns.Count > 0) { 
                    ToolStripDropDown dropDown = toolStrip.ActiveDropDowns[0] as ToolStripDropDown;

                    ToolStripMenuItem menuItem = (dropDown == null) ? null : dropDown.OwnerItem as ToolStripMenuItem;
                    if (menuItem != null && menuItem.Pressed) { 
                        menuItem.Select();
                    } 
                } 
            }
        } 

        private void OnTick(object sender, EventArgs e) {
            autoMenuExpandTimer.Enabled = false;
 
            if (CurrentItem == null) {
                return; 
            } 
            EndTransition(/*forceClose*/false);
            if (CurrentItem != null && !CurrentItem.IsDisposed &&  CurrentItem.Selected && ToolStripManager.ModalMenuFilter.InMenuMode) { 
                Debug.WriteLineIf(ToolStrip.MenuAutoExpandDebug.TraceVerbose, "[MenuTimer.OnTick] calling OnMenuAutoExpand");
                CurrentItem.OnMenuAutoExpand();
            }
        } 

 
    } 

    internal class ToolStripMenuItemInternalLayout : ToolStripItemInternalLayout { 
        private ToolStripMenuItem ownerItem;

        public ToolStripMenuItemInternalLayout(ToolStripMenuItem ownerItem) : base(ownerItem) {
            this.ownerItem = ownerItem; 
        }
 
        public bool ShowCheckMargin { 
            get{
                ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                if (menu != null) {
                    return menu.ShowCheckMargin;
                }
                return false; 
            }
        } 
        public bool ShowImageMargin { 
            get{
                ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                if (menu != null) {
                    return menu.ShowImageMargin;
                }
                return false; 
            }
        } 
 
        public bool PaintCheck {
            get { 
                return ShowCheckMargin || ShowImageMargin;
            }
        }
 
        public bool PaintImage {
            get { 
                return ShowImageMargin; 
            }
        } 
        public  Rectangle ArrowRectangle {
           get {
               if (UseMenuLayout) {
                   ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                   if (menu != null) {
                        // since menuItem.Padding isnt taken into consideration, we've got to recalc the centering of 
                        // the arrow rect per item 
                        Rectangle arrowRect = menu.ArrowRectangle;
                        arrowRect.Y = LayoutUtils.VAlign(arrowRect.Size, ownerItem.ClientBounds, ContentAlignment.MiddleCenter).Y; 
                        return arrowRect;
                   }
               }
               return Rectangle.Empty; 
           }
        } 
        public Rectangle CheckRectangle { 
            get {
                 if (UseMenuLayout) { 
                     ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu;
                     if (menu != null) {
                         Rectangle checkRectangle = menu.CheckRectangle;
                         if (ownerItem.CheckedImage != null) { 
                             int imageHeight = ownerItem.CheckedImage.Height;
                             // make sure we're vertically centered 
                             checkRectangle.Y += (checkRectangle.Height - imageHeight)/2; 
                             checkRectangle.Height = imageHeight;
                             return checkRectangle; 
                         }
                     }
                 }
                 return Rectangle.Empty; 
            }
        } 
        public override Rectangle ImageRectangle { 
            get {
                if (UseMenuLayout) { 
                    ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu;
                    if (menu != null) {

                        // since menuItem.Padding isnt taken into consideration, we've got to recalc the centering of 
                        // the image rect per item
                        Rectangle imageRect = menu.ImageRectangle; 
                        if (ownerItem.ImageScaling == ToolStripItemImageScaling.SizeToFit) { 
                            imageRect.Size = menu.ImageScalingSize;
                        } 
                        else {
                            //If we don't have an image, use the CheckedImage
                            Image image = ownerItem.Image ?? ownerItem.CheckedImage;
                            imageRect.Size = image.Size; 
                        }
                        imageRect.Y = LayoutUtils.VAlign(imageRect.Size, ownerItem.ClientBounds, ContentAlignment.MiddleCenter).Y; 
                        return imageRect; 
                    }
                } 
                return base.ImageRectangle;
            }
        }
 
        public override Rectangle TextRectangle {
            get { 
                if (UseMenuLayout) { 
                    ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu;
                    if (menu != null) { 
                        return menu.TextRectangle;
                    }
                }
                return base.TextRectangle; 
            }
        } 
 
        public bool UseMenuLayout {
            get { 
                return  ownerItem.Owner is ToolStripDropDownMenu;
            }
        }
 
        public override Size GetPreferredSize(Size constrainingSize) {
            if (UseMenuLayout) { 
                ToolStripDropDownMenu menu = ownerItem.Owner as ToolStripDropDownMenu; 
                if (menu != null) {
                    return menu.MaxItemSize; 
                }
            }
            return base.GetPreferredSize(constrainingSize);
        } 
    }
 
 } 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK