Adding a custom context menu item to Windows Form title bar

后端 未结 3 2042
攒了一身酷
攒了一身酷 2020-12-23 18:36

I found a thread on MSDN that shows how to add an item to the context menu of a winform title bar. Unfortunately it does not show how to register an event with the custom me

相关标签:
3条回答
  • 2020-12-23 18:48

    You must override WndProc Method and intercept the id of your new menu.

    try this

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WindowsFormsApplication11
    {
      public partial class Form1 : Form
      {
        public const Int32 WM_SYSCOMMAND = 0x112;
        public const Int32 MF_BYPOSITION = 0x400;
        public const Int32 MYMENU1 = 1000;
        public const Int32 MUMENU2 = 1001;
    
        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
        [DllImport("user32.dll")]
        private static extern bool InsertMenu(IntPtr hMenu,Int32 wPosition, Int32 wFlags, Int32 wIDNewItem,string lpNewItem);    
    
        public Form1()
        {
          InitializeComponent();
        }
    
        protected override void WndProc(ref Message msg)
        {
          if (msg.Msg == WM_SYSCOMMAND)
          {
            switch (msg.WParam.ToInt32())
            {
              case MYMENU1:
                MessageBox.Show("Hi from My Menu 1¡¡¡¡");
                return;
              case MUMENU2:
                MessageBox.Show("Hi from My Menu 2¡¡¡¡");
                return;
              default:
                break;
            }
          }
          base.WndProc(ref msg);
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
          IntPtr MenuHandle = GetSystemMenu(this.Handle, false);
          InsertMenu(MenuHandle, 5, MF_BYPOSITION, MYMENU1, "My Menu 1");
          InsertMenu(MenuHandle, 6, MF_BYPOSITION, MUMENU2, "My Menu 2");
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-23 18:56

    I went ahead and just added the necessary elements to the sample code to register the WndProc. This answers the basic question of registering the WndProc without altering the code as much as the previous solution. (It keeps the added menu on top of the system menu).

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
    {
                public Form1()
        {
            InitializeComponent();
    
            IntPtr hMenu = GetSystemMenu(Handle, false);
            if (hMenu != IntPtr.Zero)
            {
                var menuInfo = new MENUITEMINFO
                {
                    cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO)),
                    cch = 255,
                    dwTypeData = "Test Item",
                    fMask = 0x1 | 0x2 | 0x10,
                    fState = 0,
                    // Add an ID for your Menu Item
                    wID = 0x1,  
                    fType = 0x0
                };
    
                InsertMenuItem(hMenu, 0, true, ref menuInfo);
                DrawMenuBar(Handle);
            }
        }
    
        [DllImport("user32.dll")]
        static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
        [DllImport("user32.dll")]
        static extern bool DrawMenuBar(IntPtr hWnd);
        [DllImport("user32.dll")]
        static extern bool InsertMenuItem(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;
            public string dwTypeData;
            public uint cch;
            public IntPtr hbmpItem;
        }
    
        // Add ID for the Menu
        private const int WM_SYSCOMMAND = 0x112; 
        // Event method for the Menu
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
                                                //m.WParam = the wID you gave the Menu Item
            if ((m.Msg == WM_SYSCOMMAND) && ((int)m.WParam == 0x1))
            {
                MessageBox.Show("Test Item Dialog");
            }
    
        }
    }
    

    }

    0 讨论(0)
  • 2020-12-23 19:11

    For a separator just add:

    public const Int32 MF_SEPARATOR = 0x800;
    

    and in Form_load:

    InsertMenu(MenuHandle, 7, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); // <-- Add a menu seperator
    
    0 讨论(0)
提交回复
热议问题