c# - 如何以编程方式显示 MainMenu 的子菜单?

标签 c# .net winforms

我需要以编程方式在 Winform 中的窗体上显示主菜单的子菜单。NΕΤ 应用程序(类 MainMenuMenuItem)。

  • 例如显示包含菜单项文件的所有项目的子菜单。
  • 例如如果菜单项文本为 &File,则与按 Alt-F 相同。

我已尝试调用 OnPopup()PerformClick()PerformSelect() 并发送 WM_MenuSelect 留言;子菜单打不开。

有办法吗?

最佳答案

显示遗留菜单项 MainMenu组件,你需要调用TrackPopupMenuEx并将菜单项句柄传递给它。要在正确的位置显示它,就像您单击菜单项时一样,使用 GetMenuItemRect 获取菜单项矩形。 .

enter image description here enter image description here

代码如下:

[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);

Note: It's recommended to use a MenuStrip instead of a MainMenu.

关于c# - 如何以编程方式显示 MainMenu 的子菜单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59171718/

相关文章:

C# string.replace 去除非法字符

c# - 在客户端 Blazor 应用程序的页面中使用 [Authorize] 属性时出现授权问题

c# - Gridview Format Field as Phone Number 但有些结果是 4 digit extension,如何处理?

c# - 如何使用 C# 中的内置网页浏览器保存完整的网页

c# - 获取winform列表框的所有项目

c# - 将两个 RichTextbox 的内容附加为单个 RichText 字符串

c# - Ninject 属性注入(inject)设置问题

c# - Winform 和用户控制 - C#

c# - 运行位于 PATH 环境变量目录中的应用程序

c# - 具有复杂类型的 IDataErrorInfo