【问题标题】:Adding a custom context menu item to Windows Form title bar将自定义上下文菜单项添加到 Windows 窗体标题栏
【发布时间】:2010-12-06 04:28:38
【问题描述】:

我在 MSDN 上找到了 a thread,它展示了如何将项目添加到 Windows 窗体标题栏的上下文菜单中。

不幸的是,它没有显示如何使用自定义菜单项注册事件,我一直无法弄清楚如何去做。下面是一个示例应用程序,可以将其复制并粘贴到新的 Windows 窗体应用程序中。如何完成示例?

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

【问题讨论】:

    标签: c# winforms winapi winforms-interop


    【解决方案1】:

    您必须重写 WndProc 方法并截取新菜单的 id。

    试试这个:

    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】:

      对于分隔符,只需添加:

      public const Int32 MF_SEPARATOR = 0x800;
      

      在 Form_load 中:

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

      【讨论】:

        【解决方案3】:

        我继续,只是在示例代码中添加了必要的元素来注册 WndProc。这回答了注册 WndProc 的基本问题,而无需像以前的解决方案那样更改代码。 (它将添加的菜单保留在系统菜单的顶部)。

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

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-21
          • 1970-01-01
          • 1970-01-01
          • 2013-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多