Add to right click application menu in taskbar in .NET

放肆的年华 提交于 2019-12-09 17:25:40

问题


Most applications only have "Restore, Move, Size, Minimize, Maximize and Close", however MS SQL offers extra options "Help, Customize view". Along those lines, is it possible to add to the right click menu of an application in the task bar?

Note: I'm not referring to an icon in the notification area next to the clock.


回答1:


This is a simpler answer I found. I quickly tested it and it works.

My code:

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



回答2:


The menu on right click of the minimized program or Alt+Space or right click of the window icon in the title bar is called the SysMenu.

Here's an option for 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
}

Example of use:

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


来源:https://stackoverflow.com/questions/153460/add-to-right-click-application-menu-in-taskbar-in-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!