簡體   English   中英

如何以編程方式顯示 MainMenu 的子菜單?

[英]How to show sub-menu of a MainMenu programmatically?

我需要以編程方式在 Winform .NET 應用程序中的表單上顯示主菜單的子菜單(使用MenuItemMainMenu )。

  • 例如顯示帶有菜單項文件的所有項目的子菜單。
  • 例如,如果菜單項文本為 &File,則與按 Alt-F 相同。

我嘗試調用OnPopup()PerformClick()PerformSelect()並發送WM_MenuSelect消息; 子菜單打不開。

有沒有辦法做到這一點?

要顯示舊版MainMenu組件的菜單項,您需要調用TrackPopupMenuEx並將菜單項句柄傳遞給它。 要在正確的位置顯示它,就像單擊菜單項一樣,請使用GetMenuItemRect獲取菜單項矩形。

在此處輸入圖片說明 在此處輸入圖片說明

這是代碼:

[DllImport("user32.dll")]
static extern int TrackPopupMenuEx(IntPtr hmenu, uint fuFlags,
    int x, int y, IntPtr hwnd, IntPtr lptpm);
[DllImport("user32.dll")]
static extern bool GetMenuItemRect(IntPtr hWnd, IntPtr hMenu,
    uint uItem, out RECT lprcItem);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
public struct RECT { public int Left, Top, Right, Bottom; }
const int TPM_RIGHTBUTTON = 0x2;
const int TPM_RETURNCMD = 0x100;
const int WM_SYSCOMMAND = 0x112;

public void ShowSubMenu(MenuItem menuItem, bool asContextMenu = false)
{
    var mainMenu = menuItem.GetMainMenu();
    var form = mainMenu.GetForm();
    var x = 0; var y = 0;
    if (asContextMenu)
    {
        x = MousePosition.X; y = MousePosition.Y;
    }
    else
    {
        GetMenuItemRect(form.Handle, mainMenu.Handle, 
            (uint)menuItem.Index, out RECT rect);
        x = rect.Left; y = rect.Bottom;
    }
    var command = TrackPopupMenuEx(menuItem.Handle, TPM_RETURNCMD | TPM_RIGHTBUTTON,
        x, y, form.Handle, IntPtr.Zero);
    if (command > 0)
        SendMessage(form.Handle, WM_SYSCOMMAND, command, IntPtr.Zero);
}

要使用它,只需這樣稱呼它:

ShowSubMenu(fileMenuItem);

如果通過將 false 傳遞給showAxContextMenu來調用它,它將在鼠標位置顯示子菜單:

ShowSubMenu(fileMenuItem, true);

注意:建議使用MenuStrip而不是MainMenu

您需要在 Form 的構造函數或 Load 事件中將所需的菜單項克隆到新的ContextMenu組件,並將其附加到目標控件的ContextMenu (而不是ContextMenuStrip )屬性。

例如,要將File菜單中的NewOpenSave項目克隆到新的ContextMenu

var cmn = new ContextMenu();

cmn.MenuItems.AddRange(
    new[]
    {
        mnuFileNew.CloneMenu(),
        mnuFileOpen.CloneMenu(),
        mnuFileSave.CloneMenu()
    }
);

或者,如果您需要它們:

mnuFile.MenuItems.Cast<MenuItem>().ToList()
    .ForEach(m => cmn.MenuItems.Add(m.CloneMenu()));

請注意,子項目也將被克隆(如果有)。

並將其分配給ContextMenu屬性:

this.ContextMenu = cmn;

現在右鍵單擊窗體,新的ContextMenu將彈出,單擊一個項目,將執行相同的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM