在.NET的任务栏中添加到右键单击应用程序菜单

问题描述 投票:7回答:2

大多数应用程序仅具有“还原,移动,大小,最小化,最大化和关闭”,但是MS SQL提供了附加选项“帮助,自定义视图”。沿着这些思路,是否可以在任务栏中添加到应用程序的右键菜单?

注意:我不是指的是时钟旁边的通知区域中的图标。

.net windows taskbar
2个回答
1
投票

这是我发现的更简单的answer。我很快对其进行了测试,并且可以正常工作。

我的代码:

    private const int WMTaskbarRClick = 0x0313;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WMTaskbarRClick:
                {
                    // Show your own context menu here, i do it like this
                    // there's a context menu present on my main form so i use it

                    MessageBox.Show("I see that.");

                    break;
                }
            default:
                {
                    base.WndProc(ref m);
                    break;
                }
        }
    }

0
投票

在最小化程序或Alt + Space上单击鼠标右键的菜单,或在标题栏中右键单击窗口图标的菜单称为SysMenu。

WPF的一个选项:

// License MIT 2019 Mitch Gaffigan
// https://stackoverflow.com/a/58160366/138200
public class SysMenu
{
    private readonly Window Window;
    private readonly List<MenuItem> Items;
    private bool isInitialized;
    private IntPtr NextID = (IntPtr)1000;
    private int StartPosition = 5;

    public SysMenu(Window window)
    {
        this.Items = new List<MenuItem>();
        this.Window = window ?? throw new ArgumentNullException(nameof(window));
        this.Window.SourceInitialized += this.Window_SourceInitialized;
    }

    class MenuItem
    {
        public IntPtr ID;
        public string Text;
        public Action OnClick;
    }

    public void AddSysMenuItem(string text, Action onClick)
    {
        if (string.IsNullOrWhiteSpace(text))
        {
            throw new ArgumentNullException(nameof(text));
        }
        if (onClick == null)
        {
            throw new ArgumentNullException(nameof(onClick));
        }

        var thisId = NextID;
        NextID += 1;

        var newItem = new MenuItem()
        {
            ID = thisId,
            Text = text,
            OnClick = onClick
        };
        Items.Add(newItem);
        var thisPosition = StartPosition + Items.Count;

        if (isInitialized)
        {
            var hwndSource = PresentationSource.FromVisual(Window) as HwndSource;
            if (hwndSource == null)
            {
                return;
            }
            var hSysMenu = GetSystemMenu(hwndSource.Handle, false);
            InsertMenu(hSysMenu, thisPosition, MF_BYPOSITION, thisId, text);
        }
    }

    private void Window_SourceInitialized(object sender, EventArgs e)
    {
        var hwndSource = PresentationSource.FromVisual(Window) as HwndSource;
        if (hwndSource == null)
        {
            return;
        }

        hwndSource.AddHook(WndProc);

        var hSysMenu = GetSystemMenu(hwndSource.Handle, false);

        /// Create our new System Menu items just before the Close menu item
        InsertMenu(hSysMenu, StartPosition, MF_BYPOSITION | MF_SEPARATOR, IntPtr.Zero, string.Empty);
        int pos = StartPosition + 1;
        foreach (var item in Items)
        {
            InsertMenu(hSysMenu, pos, MF_BYPOSITION, item.ID, item.Text);
            pos += 1;
        }

        isInitialized = true;
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_SYSCOMMAND)
        {
            var item = Items.FirstOrDefault(d => d.ID == wParam);
            if (item != null)
            {
                item.OnClick();
                handled = true;
                return IntPtr.Zero;
            }
        }

        return IntPtr.Zero;
    }

    #region Win32

    private const Int32 WM_SYSCOMMAND = 0x112;
    private const Int32 MF_SEPARATOR = 0x800;
    private const Int32 MF_BYPOSITION = 0x400;
    private const Int32 MF_STRING = 0x0;

    [DllImport("user32.dll")]
    private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [DllImport("user32.dll")]
    private static extern bool InsertMenu(IntPtr hMenu, int wPosition, int wFlags, IntPtr wIDNewItem, string lpNewItem);

    #endregion
}

使用示例:

internal partial class MainWindow : Window
{
    public MainWindow()
    {
        var sysMenu = new SysMenu(this);
        sysMenu.AddSysMenuItem("Quit", miQuit_Click);
        sysMenu.AddSysMenuItem("Show debug tools", miShowDebug_Click);
    }

    private void miQuit_Click()
    {
        // "On-Click" logic here
    }

    private void miShowDebug_Click()
    {
        // "On-Click" logic here
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.