【问题标题】:C# ContextMenu Remove Default SelectionC# ContextMenu 删除默认选择
【发布时间】:2011-08-18 17:23:13
【问题描述】:

好吧,这个问题似乎太简单了,但我已经浪费了足够多的时间来寻找如何做到这一点。我在移动设备上使用 CE 6.5,并且我有一个带有六个 MenuItem 的 ContextMenu。当菜单弹出时,列表中的第一个项目会自动突出显示。我想删除此突出显示,因为它使我的一些用户感到困惑,认为它是当前状态。我查看了 ContextMenu 及其所有变量和 MenuItem 并没有找到如何删除第一项的自动突出显示。 MainMenu 也是如此。

【问题讨论】:

    标签: c# mobile compact-framework contextmenu


    【解决方案1】:

    不幸的是,我认为答案是不能。今天下午我付出了很大的努力来获取该菜单,但我无法获得操作系统允许我使用的有效 HMENU。如果您想继续尝试追逐我在代码上的路径,但我真的认为这是一个死胡同。在这一点上,如果您真的需要该功能,我会考虑 P/Invoking 菜单的所有内容(创建、填充等)。

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Reflection;
    using System.Runtime.InteropServices;
    
    using UINT = System.UInt32;
    using HMENU = System.IntPtr;
    using HBITMAP = System.IntPtr;
    using DWORD = System.UInt32;
    using LPTSTR = System.IntPtr;
    
    namespace MenuTest
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                contextMenu.MenuItems.Add(new MenuItem() { Text = "Item A" });
                contextMenu.MenuItems.Add(new MenuItem() { Text = "Item B" });
                contextMenu.MenuItems.Add(new MenuItem() { Text = "Item C" });
                contextMenu.MenuItems.Add(new MenuItem() { Text = "Item D" });
    
                this.MouseDown += new MouseEventHandler(Form1_MouseDown);
                contextMenu.Popup += new EventHandler(contextMenu_Popup);
            }
    
            void contextMenu_Popup(object sender, EventArgs e)
            {
                var type = contextMenu.GetType();
                var members = type.GetMembers(
                              BindingFlags.NonPublic | BindingFlags.Instance);
                var menuMember = type.GetField("m_hmnu", 
                                 BindingFlags.NonPublic | BindingFlags.Instance);
                var hMenu = (HMENU)menuMember.GetValue(contextMenu);
    
                var info = new MENUITEMINFO();
                info.cbSize = (uint)Marshal.SizeOf(info);
                info.fMask = MIIM_STATE;
                var result = GetMenuItemInfo(hMenu, 0, true, out info);
                if (!result)
                {
                    var err = Marshal.GetLastWin32Error();
                    if (err == 0x0579) MessageBox.Show("Invalid menu handle");
                    return;
                }
                info.fMask = MIIM_STATE;
                info.fState &= (~MFS_HILITE);
                result = SetMenuItemInfo(hMenu, 0, true, ref info); 
            }
    
            void Form1_MouseDown(object sender, MouseEventArgs e)
            {
                contextMenu.Show(this, new Point(e.X, e.Y));
            }
    
            private const uint MIIM_STATE = 1;
            private const uint MFS_UNHILITE = 0;
            private const uint MFS_HILITE = 0x80;        
    
            //typedef struct tagMENUITEMINFO {
            //  UINT cbSize; 
            //  UINT fMask; 
            //  UINT fType; 
            //  UINT fState; 
            //  UINT wID; 
            //  HMENU hSubMenu; 
            //  HBITMAP hbmpChecked; 
            //  HBITMAP hbmpUnchecked; 
            //  DWORD dwItemData; 
            //  LPTSTR dwTypeData; 
            //  UINT cch; 
            //} MENUITEMINFO, FAR* LPMENUITEMINFO; 
            private struct MENUITEMINFO
            {
                public UINT cbSize;
                public UINT fMask;
                public UINT fType;
                public UINT fState;
                public UINT wID;
                public HMENU hSubMenu;
                public HBITMAP hbmpChecked;
                public HBITMAP hbmpUnchecked;
                public DWORD dwItemData;
                public LPTSTR dwTypeData;
                public UINT cch; 
            }
    
            //BOOL SetMenuItemInfo(
            //  HMENU hMenu,
            //  UINT uItem,
            //  BOOL fByPosition,
            //  LPCMENUITEMINFO lpmii
            //);
            [DllImport("coredll", SetLastError = true)]
            private static extern bool SetMenuItemInfo(HMENU hMenu, UINT uItem, 
                                       [MarshalAs(UnmanagedType.Bool)]bool fByPosition, 
                                       ref MENUITEMINFO lpmii);
    
            //BOOL GetMenuItemInfo(
            //  HMENU hMenu,
            //  UINT uItem,
            //  BOOL fByPosition,
            //  LPMENUITEMINFO lpmii
            //);
            [DllImport("coredll", SetLastError = true)]
            private static extern bool GetMenuItemInfo(HMENU hMenu, UINT uItem, 
                                       [MarshalAs(UnmanagedType.Bool)]bool fByPosition, 
                                       out MENUITEMINFO lpmii);
    
            //HMENU GetSubMenu(
            //  HMENU hMenu,
            //  int nPos
            //);
            [DllImport("coredll", SetLastError = true)]
            private static extern HMENU GetSubMenu(HMENU hMenu, int nPos);
        }
    }
    

    编辑

    我知道我在某处有代码可以完成所有这些工作。我们曾经出售一个商业 PopupMenu 控件,它包含所有用于创建菜单的 P/Invokes。控件的销售额很小,所以几年前我们将其从我们的产品线中撤出。我现在已将其作为开源 over on Codeplex 发布。

    【讨论】:

    • 如果你能告诉我如何 P/Invoke 它,因为我还是 Windows CE/C# 环境的新手(Java coder by trade)
    • 这将是一个漫长的教训 - 不仅仅是在这里发帖。它与我上面所做的相同,但是您必须 P/Invoke 来创建菜单和项目,然后将菜单单击处理程序连接到您的托管委托。这不是太难 - 我会给它 4 分左右(满分 10 分),但它会有点长。
    猜你喜欢
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多