使WPF系统上下文菜单项可切换

时间:2010-11-10 11:49:16

标签: wpf contextmenu user32 winapi

我有以下代码,它在窗口镶边显示的系统上下文菜单中添加了“Always on Top”项。它工作正常,但我希望它显示一个复选标记或类似标记,表明它是否已打开/关闭。

知道我该怎么做吗?

public RibbonShell()
{
    InitializeComponent();

    Loaded += (s,e) =>
                {
                    // Get the Handle for the Forms System Menu
                    var systemMenuHandle = GetSystemMenu(Handle, false);

                    // Create our new System Menu items just before the Close menu item
                    InsertMenu(systemMenuHandle, 5, MfByposition | MfSeparator, 0, string.Empty); // <-- Add a menu seperator
                    InsertMenu(systemMenuHandle, 6, MfByposition, SettingsSysMenuId, "Always on Top");

                    // Attach our WindowCommandHandler handler to this Window
                    var source = HwndSource.FromHwnd(Handle);
                    source.AddHook(WindowCommandHandler);
                };
}

#region Win32 API Stuff

// Define the Win32 API methods we are going to use
[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);

/// Define our Constants we will use
private const int WmSyscommand = 0x112;
private const int MfSeparator = 0x800;
private const int MfByposition = 0x400;

#endregion

// The constants we'll use to identify our custom system menu items
private const int SettingsSysMenuId = 1000;

/// <summary>
/// This is the Win32 Interop Handle for this Window
/// </summary>
public IntPtr Handle
{
    get { return new WindowInteropHelper(this).Handle; }
}

private IntPtr WindowCommandHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    // Check if a System Command has been executed
    if (msg == WmSyscommand && wParam.ToInt32() == SettingsSysMenuId)
    {
        Topmost = !Topmost;
        handled = true;
    }

    return IntPtr.Zero;
}

1 个答案:

答案 0 :(得分:4)

每当您更改Topmost时,您需要调用CheckMenuItem。有关详细信息,请参阅CheckMenuItem documentaton。这是你需要的P / Invoke签名和常量:

[DllImport("user32.dll")] 
private static extern bool CheckMenuItem(IntPtr hMenu, Int32 uIDCheckItem, Int32 uCheck); 

private const int MfChecked = 8;
private const int MfUnchecked = 0;

现在检查项目,只需:

CheckMenuItem(systemMenuHandle, SettingsSysMenuId, MfChecked);

并取消选中:

CheckMenuItem(systemMenuHandle, SettingsSysMenuId, MfUnchecked);