You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF桌面应用中修改MainWindow默认上下文菜单

在WPF中修改MainWindow默认标题栏上下文菜单(代码实现)

WPF窗口标题栏的默认右键菜单是系统菜单,并非WPF内置的ContextMenu控件,所以你之前通过this.ContextMenu或查找资源的方式根本获取不到它。要修改这个菜单,必须借助Win32 API来操作系统菜单句柄。

实现步骤及代码

  1. 声明必要的Win32 API函数
    在MainWindow类所在的命名空间下添加以下API声明:
using System.Runtime.InteropServices;

public static class Win32Api
{
    [DllImport("user32.dll")]
    public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [DllImport("user32.dll")]
    public static extern bool AppendMenu(IntPtr hMenu, uint uFlags, uint uIDNewItem, string lpNewItem);

    public const uint MF_SEPARATOR = 0x00000800;
    public const uint MF_STRING = 0x00000000;
}
  1. 定义自定义菜单项的ID
    在MainWindow类中定义唯一的菜单ID(避免和系统菜单原有ID冲突,建议从1000开始):
private const uint ID_MENU_ITEM1 = 1000;
private const uint ID_MENU_ITEM2 = 1001;
private const uint ID_MENU_ITEM3 = 1002;
  1. 在窗口加载时修改系统菜单
    修改你的Window_Loaded事件处理方法:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    if (CanShowDevMenu)
    {
        // 获取窗口句柄
        IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
        // 获取系统菜单句柄
        IntPtr sysMenu = Win32Api.GetSystemMenu(hwnd, false);

        if (sysMenu != IntPtr.Zero)
        {
            // 添加分隔线
            Win32Api.AppendMenu(sysMenu, Win32Api.MF_SEPARATOR, 0, string.Empty);
            // 添加自定义菜单项
            Win32Api.AppendMenu(sysMenu, Win32Api.MF_STRING, ID_MENU_ITEM1, "Item 1");
            Win32Api.AppendMenu(sysMenu, Win32Api.MF_STRING, ID_MENU_ITEM2, "Item 2");
            Win32Api.AppendMenu(sysMenu, Win32Api.MF_STRING, ID_MENU_ITEM3, "Item 3");
        }
    }
}
  1. 重写WndProc处理菜单点击事件
    在MainWindow类中重写窗口消息处理逻辑,响应自定义菜单项的点击:
protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    // 注册窗口消息钩子
    HwndSource source = HwndSource.FromHwnd(new System.Windows.Interop.WindowInteropHelper(this).Handle);
    source.AddHook(WndProc);
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    const int WM_SYSCOMMAND = 0x0112;

    if (msg == WM_SYSCOMMAND)
    {
        uint command = (uint)wParam.ToInt32();
        switch (command)
        {
            case ID_MENU_ITEM1:
                // 替换为Item 1的实际处理逻辑
                MessageBox.Show("Item 1 clicked");
                handled = true;
                break;
            case ID_MENU_ITEM2:
                // 替换为Item 2的实际处理逻辑
                MessageBox.Show("Item 2 clicked");
                handled = true;
                break;
            case ID_MENU_ITEM3:
                // 替换为Item 3的实际处理逻辑
                MessageBox.Show("Item 3 clicked");
                handled = true;
                break;
        }
    }
    return IntPtr.Zero;
}

注意事项

  • 系统菜单默认ID通常小于1000,自定义ID从1000开始可避免冲突。
  • 若需恢复默认系统菜单,调用GetSystemMenu(hwnd, true)即可。

内容的提问来源于stack exchange,提问作者Greg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:05:15