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

发布于 2024-10-01 09:10:23 字数 2011 浏览 10 评论 0原文

我有以下代码,它将“始终位于顶部”项目添加到窗口镶边上显示的系统上下文菜单中。它工作正常,但我希望它显示一个复选标记或类似的标记来指示它是否已打开/关闭。

知道我该怎么做吗?

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;
}

I have the following code, which adds an 'Always on Top' item to the system context menu as displayed on the window chrome. It works correctly, but I'd like it to display a check mark or similar to indicate if it's been toggled on/off.

Any idea how I can do this?

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

楠木可依 2024-10-08 09:10:23

每当更改 Topmost 时,您都需要调用 CheckMenuItem。有关详细信息,请参阅 CheckMenuItem 文档。以下是您需要的 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);

You need to call CheckMenuItem whenever you change Topmost. See the CheckMenuItem documentaton for details. Here's the P/Invoke signature and constants you'll need:

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

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

Now to check the item, just:

CheckMenuItem(systemMenuHandle, SettingsSysMenuId, MfChecked);

and to uncheck:

CheckMenuItem(systemMenuHandle, SettingsSysMenuId, MfUnchecked);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文