简体   繁体   English

向 Windows 窗体标题栏添加自定义上下文菜单项

[英]Adding a custom context menu item to Windows Form title bar

I found a thread on MSDN that shows how to add an item to the context menu of a Windows Forms title bar.我在 MSDN 上找到了一个线程,显示了如何将项目添加到 Windows 窗体标题栏的上下文菜单中。

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 application that can be copied and pasted into a new Windows Forms application.下面是一个示例应用程序,可以将其复制并粘贴到新的 Windows 窗体应用程序中。 How can I complete the sample?我怎样才能完成样本?

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

You must override the WndProc method and intercept the id of your new menu.您必须覆盖WndProc方法并拦截新菜单的 id。

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

For a separator just add:对于分隔符,只需添加:

public const Int32 MF_SEPARATOR = 0x800;

and in Form_load:并在 Form_load 中:

InsertMenu(MenuHandle, 7, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); // <-- Add a menu seperator

I went ahead and just added the necessary elements to the sample code to register the WndProc.我继续在示例代码中添加了必要的元素来注册 WndProc。 This answers the basic question of registering the WndProc without altering the code as much as the previous solution.这回答了注册 WndProc 的基本问题,而无需像以前的解决方案一样更改代码。 (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");
        }

    }
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM