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

7
大多数应用程序只有“还原、移动、大小、最小化、最大化和关闭”这些选项,但是 MS SQL 提供了额外的选项“帮助、自定义视图”。那么,在任务栏中的应用程序的右键菜单中添加选项是否可行呢?
注意:我并不是指靠近时钟的通知区域中的图标。

1
我不能直接帮助你,但你所提到的菜单是系统菜单。这与在窗口标题栏中单击应用程序图标时显示的菜单相同。也许这会帮助你或其他人找到答案 :) - OregonGhost
这篇文章使用C#为您提供了一个漫游。它讲解如何使用Windows API将系统菜单项添加到窗体中。 - Mitchel Sellers
2个回答

1

这是我找到的一个更简单的答案。我快速测试了一下,它有效果。

我的代码:

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

但是,如果您只是显示菜单,则无法将其与现有菜单集成。 - Mitchel Sellers
2
似乎只有在按住“SHIFT”键的同时右键单击时才有效。 - farosch
@farosch 看起来是针对 Windows XP 菜单(从 还原移动大小 开始的那个菜单),它是通过在 Vista+ 上按 shift+click 显示的。这通常不是您想要覆盖的菜单。 - c z

0

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

这里有一个WPF选项:

// License MIT 2019 Mitch Gaffigan
// https://dev59.com/p0XRa4cB1Zd3GeqPrFxA#58160366
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
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接