none
Adding to the global context menu

    Question

  • I want to add a function to the global context menu.  The same one used by Explorer.  Being I havent found any managed code that can accomplish this task I got a sickening feeling that I need to use a COM object from the Windows API.  Anybody got some insight?

     

     

    This guy was trying to do this 2 years ago and never got an answer >.< http://www.thescripts.com/forum/thread235380.html

    Friday, March 28, 2008 6:48 PM

Answers

  • Here you go.  I just modified the Pinvoke.net example on how to remove the close button.  This seems to work fine.  Little sloppy though


        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                AddMenuItem(this);
            }



            public static void RemoveCloseButton(Form frm)
            {
                IntPtr hMenu;
                int n;
                hMenu = GetSystemMenu(frm.Handle, false);
                if (hMenu != IntPtr.Zero)
                {
                    n = GetMenuItemCount(hMenu);
                    if (n > 0)
                    {
                        RemoveMenu(hMenu, (uint)(n - 1), MF_BYPOSITION | MF_REMOVE);
                        RemoveMenu(hMenu, (uint)(n - 2), MF_BYPOSITION | MF_REMOVE);
                        DrawMenuBar(frm.Handle);
                    }
                }
            }

            public static void AddMenuItem(Form frm)
            {
                IntPtr hMenu;
                int n;
                hMenu = GetSystemMenu(frm.Handle, false);
                if (hMenu != IntPtr.Zero)
                {
                    n = GetMenuItemCount(hMenu);
                    if (n > 0)
                    {
                        //RemoveMenu(hMenu, (uint)(n - 1), MF_BYPOSITION | MF_REMOVE);
                        //RemoveMenu(hMenu, (uint)(n - 2), MF_BYPOSITION | MF_REMOVE);
                        MENUITEMINFO menuInfo = new MENUITEMINFO();
                        menuInfo.cbSize = MENUITEMINFO.sizeOf;
                        menuInfo.cch = 255;
                        menuInfo.dwTypeData = "Test Item";
                        menuInfo.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
                        menuInfo.fState = 0;
                        menuInfo.fType = MFT_STRING;
                        //menuInfo.hSubMenu =

                        InsertMenuItem(hMenu, (uint)n, true, ref menuInfo);
                        DrawMenuBar(frm.Handle);
                    }
                }
            }


           
            private const int MIIM_STATE = 0x1;
            private const int MIIM_ID = 0x2;
            private const int MIIM_TYPE = 0x10;
            private const int MFT_SEPARATOR = 0x800;
            private const int MFT_STRING = 0x0;
            private const int MFS_ENABLED = 0x0;
            private const int MFS_CHECKED = 0x8;
       
            private const Int32 MF_BYPOSITION = 0x400;
            private const Int32 MF_REMOVE = 0x1000;

            [DllImport("user32.dll")]
            static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
            [DllImport("user32.dll")]
            static extern int GetMenuItemCount(IntPtr hMenu);
            [DllImport("user32.dll")]
            static extern bool DrawMenuBar(IntPtr hWnd);
            [DllImport("user32.dll")]
            static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);

            [DllImport("user32.dll")]
            static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool fByPosition,
               [In] ref MENUITEMINFO lpmii);

            [DllImport("user32.dll")]
            static extern bool SetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPosition,
               [In] ref MENUITEMINFO lpmii);

            [StructLayout(LayoutKind.Sequential)]
            public struct MENUITEMINFO
            {
                public uint cbSize;
                public uint fMask;
                public uint fType;
                public uint fState;
                public uint wID;
                public IntPtr hSubMenu;
                public IntPtr hbmpChecked;
                public IntPtr hbmpUnchecked;
                public IntPtr dwItemData; //<- ItemData is up! by haijer
                public string dwTypeData;
                public uint cch;
                public IntPtr hbmpItem;

                // return the size of the structure
                internal static uint sizeOf
                {
                    get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
                }
            }

        }


    Saturday, March 29, 2008 2:52 AM

All replies

  • Here you go.  I just modified the Pinvoke.net example on how to remove the close button.  This seems to work fine.  Little sloppy though


        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                AddMenuItem(this);
            }



            public static void RemoveCloseButton(Form frm)
            {
                IntPtr hMenu;
                int n;
                hMenu = GetSystemMenu(frm.Handle, false);
                if (hMenu != IntPtr.Zero)
                {
                    n = GetMenuItemCount(hMenu);
                    if (n > 0)
                    {
                        RemoveMenu(hMenu, (uint)(n - 1), MF_BYPOSITION | MF_REMOVE);
                        RemoveMenu(hMenu, (uint)(n - 2), MF_BYPOSITION | MF_REMOVE);
                        DrawMenuBar(frm.Handle);
                    }
                }
            }

            public static void AddMenuItem(Form frm)
            {
                IntPtr hMenu;
                int n;
                hMenu = GetSystemMenu(frm.Handle, false);
                if (hMenu != IntPtr.Zero)
                {
                    n = GetMenuItemCount(hMenu);
                    if (n > 0)
                    {
                        //RemoveMenu(hMenu, (uint)(n - 1), MF_BYPOSITION | MF_REMOVE);
                        //RemoveMenu(hMenu, (uint)(n - 2), MF_BYPOSITION | MF_REMOVE);
                        MENUITEMINFO menuInfo = new MENUITEMINFO();
                        menuInfo.cbSize = MENUITEMINFO.sizeOf;
                        menuInfo.cch = 255;
                        menuInfo.dwTypeData = "Test Item";
                        menuInfo.fMask = MIIM_STATE | MIIM_ID | MIIM_TYPE;
                        menuInfo.fState = 0;
                        menuInfo.fType = MFT_STRING;
                        //menuInfo.hSubMenu =

                        InsertMenuItem(hMenu, (uint)n, true, ref menuInfo);
                        DrawMenuBar(frm.Handle);
                    }
                }
            }


           
            private const int MIIM_STATE = 0x1;
            private const int MIIM_ID = 0x2;
            private const int MIIM_TYPE = 0x10;
            private const int MFT_SEPARATOR = 0x800;
            private const int MFT_STRING = 0x0;
            private const int MFS_ENABLED = 0x0;
            private const int MFS_CHECKED = 0x8;
       
            private const Int32 MF_BYPOSITION = 0x400;
            private const Int32 MF_REMOVE = 0x1000;

            [DllImport("user32.dll")]
            static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
            [DllImport("user32.dll")]
            static extern int GetMenuItemCount(IntPtr hMenu);
            [DllImport("user32.dll")]
            static extern bool DrawMenuBar(IntPtr hWnd);
            [DllImport("user32.dll")]
            static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);

            [DllImport("user32.dll")]
            static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool fByPosition,
               [In] ref MENUITEMINFO lpmii);

            [DllImport("user32.dll")]
            static extern bool SetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPosition,
               [In] ref MENUITEMINFO lpmii);

            [StructLayout(LayoutKind.Sequential)]
            public struct MENUITEMINFO
            {
                public uint cbSize;
                public uint fMask;
                public uint fType;
                public uint fState;
                public uint wID;
                public IntPtr hSubMenu;
                public IntPtr hbmpChecked;
                public IntPtr hbmpUnchecked;
                public IntPtr dwItemData; //<- ItemData is up! by haijer
                public string dwTypeData;
                public uint cch;
                public IntPtr hbmpItem;

                // return the size of the structure
                internal static uint sizeOf
                {
                    get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
                }
            }

        }


    Saturday, March 29, 2008 2:52 AM
  • This is top article it even works in x64 version of Vista. I had a similar problem (trying to add to the shell context menu an item) and only this way of marshaling the structures/methods worked on x64.

    Thursday, May 01, 2008 9:56 AM
  • How do you hook the event with the new menu item?

    Thanks.
    Friday, August 29, 2008 1:53 PM