Adding a custom context menu item to Windows Form title bar

前提是你 提交于 2019-12-18 10:36:29

问题


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 menu item and I have been unable to figure out how to do it. Below is a sample app that can be copied and pasted into a new Windows Forms Application. I would appreciate it if someone could complete the sample for me. Thanks

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,
                       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;
        }
    }
}

回答1:


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");
    }
  }
}



回答2:


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



回答3:


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");
        }

    }
}

}



来源:https://stackoverflow.com/questions/1557904/adding-a-custom-context-menu-item-to-windows-form-title-bar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!