大多数应用程序只有“恢复、移动、大小、最小化、最大化和关闭”,但是MS SQL提供了额外的选项“帮助、自定义视图”。按照这些思路,是否可以在任务栏中添加到应用程序的右键菜单?
注意:我指的不是时钟旁边通知区域中的图标。
这是我找到的一个更简单的答案。我很快测试了它并且它有效。
我的代码:
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;
}
}
}
右键单击最小化程序或 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
}
}