public sealed partial class MainWindow : Window
{
private const uint WM_LBUTTONUP = 0x0202; // Left button up
private const uint WM_COMMAND = 0x0111; // Left button up
private const int WM_SYSCOMMAND = 0x0112; //
private const int WM_APP = 0x8000; // Custom Windows message
private const uint NIM_ADD = 0x00000000;
private const uint NIM_DELETE = 0x00000002;
private const uint NIF_MESSAGE = 0x00000001;
private const uint NIF_ICON = 0x00000002;
private const uint NIF_TIP = 0x00000004;
public const int LR_LOADFROMFILE = 0x00000010;
private const int ID_TRAY_EXIT = 0x2000;
private const int ID_TRAY_OPEN = 0x2001;
private const int WS_MAXIMIZEBOX = 0x00010000;
private const int GWL_STYLE = -16;
public const int IMAGE_ICON = 1;
private IntPtr _prevWndProc;
private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
private WndProcDelegate _wndProcDelegate;
private IntPtr _hwnd;
[DllImport("user32.dll")]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, WndProcDelegate newProc);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, int newProc);
[DllImport("user32.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreatePopupMenu();
[DllImport("user32.dll")]
private static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool AppendMenu(IntPtr hMenu, uint uFlags, uint uIDNewItem, string lpNewItem);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool DestroyMenu(IntPtr hMenu);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadImage(IntPtr hInst, string lpszName, UInt32 uType, int cxDesired, int cyDesired, UInt32 fuLoad);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern bool Shell_NotifyIcon(uint dwMessage, [In] ref NOTIFYICONDATA lpdata);
public MainWindow()
{
this.InitializeComponent();
_wndProcDelegate = new WndProcDelegate(WndProc);
_hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
_prevWndProc = SetWindowLongPtr(_hwnd, GWLP_WNDPROC, _wndProcDelegate); // GWLP_WNDPROC
CreateNotifyIcon();
this.Closed += MainWindow_Closed;
}
private const int GWLP_WNDPROC = -4;
private void myButton_Click(object sender, RoutedEventArgs e)
{
HiddenButton.Content = "Clicked";
}
private void CreateNotifyIcon()
{
NOTIFYICONDATA notifyIconData = new NOTIFYICONDATA
{
cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONDATA)),
hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this), // Correctly obtain the window handle
uID = 1,
uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP,
uCallbackMessage = WM_APP + 1, // Custom message ID
szTip = "WinUI 3 System Tray Sample",
hIcon = LoadImage(IntPtr.Zero, @".\Properties\Icon\mydevice_ic_dark.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE) // Extracting icon from the executable
};
Shell_NotifyIcon(NIM_ADD, ref notifyIconData); // NIM_ADD to add the icon
}
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
Debug.WriteLine($"msg: {msg}, lParam: {lParam}, wParam: {wParam & 0xFFFF}");
if( msg == WM_APP +1)
{
if (lParam.ToInt32() == WM_LBUTTONUP)
{
NotifyIcon_Click(this, EventArgs.Empty);
}
else if (lParam.ToInt32() == 0x0205) // WM_RBUTTONUP (right button up)
{
ShowContextMenu();
}
Debug.WriteLine($"msg: {msg}, lParam: {lParam.ToInt32()}");
return IntPtr.Zero;
}
else if(msg == WM_COMMAND)
{
int commandID = wParam.ToInt32() & 0xFFFF;
if(commandID == ID_TRAY_OPEN)
{
NotifyIcon_Click(this, EventArgs.Empty);
}
else if (commandID == ID_TRAY_EXIT) {
Application.Current.Exit();
}
Debug.WriteLine($"msg: {msg}, lParam: {lParam}, wParam: {wParam.ToInt32() & 0xFFFF}");
}
else if(msg == WM_SYSCOMMAND)
{
int commandID = wParam.ToInt32() & 0xFFFF;
if(commandID == ID_TRAY_OPEN)
{
NotifyIcon_Click(this, EventArgs.Empty);
}
else if (commandID == ID_TRAY_EXIT) {
Application.Current.Exit();
}
Debug.WriteLine($"msg: {msg}, lParam: {lParam}, wParam: {wParam.ToInt32() & 0xFFFF}");
}
return CallWindowProc(_prevWndProc, hWnd, msg, wParam, lParam);
}
private void ShowContextMenu()
{
// Get the current cursor position
if (GetCursorPos(out POINT cursorPos))
{
IntPtr hMenu = CreatePopupMenu();
AppendMenu(hMenu, 0x0, ID_TRAY_OPEN, "Open");
AppendMenu(hMenu, 0x0, ID_TRAY_EXIT, "Exit");
SetForegroundWindow(hMenu);
// Show the menu at the current cursor position
TrackPopupMenu(hMenu, 0x100, cursorPos.X, cursorPos.Y, 0, _hwnd, IntPtr.Zero);
DestroyMenu(hMenu);
}
}
private void MainWindow_Closed(object sender, WindowEventArgs e)
{
e.Handled = true;
this.AppWindow.Hide();
// Show notification icon in the system tray
}
private void NotifyIcon_Click(object sender, EventArgs e)
{
this.AppWindow.Show();
this.Activate();
}
public void ShowWindow()
{
this.AppWindow.Show();
this.Activate();
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct NOTIFYICONDATA
{
public uint cbSize;
public IntPtr hWnd;
public uint uID;
public uint uFlags;
public uint uCallbackMessage;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szTip;
public uint dwState;
public uint dwStateMask;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szInfo;
public uint uTimeoutOrVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string szInfoTitle;
public uint dwInfoFlags;
public Guid guidItem;
public IntPtr hBalloonIcon;
}
}
中,在处理托盘和菜单项时,我从未收到消息WM_Command
和WM_Command和
WM_SysCommand
。我还希望当我单击其他任何地方并需要在托盘图标内设置图标(当前为空)时,菜单也会消失。我无法运行H.notifyicon,目前不想使用它,因为它不完整。 有人可以帮助我如何在winui3中制作适当的系统托盘图标? 根据TrackPopupMenuDocument 如果您在uflags参数中指定tpm_returncmd(100),则返回 值是用户选择的项目的菜单项目标识符。 因此,您可以处理用户的点击结果。
“我也希望菜单在我单击任何地方时消失”显示通知图标的上下文菜单,当前窗口
在申请通话之前必须是前景窗口
TrackPopupMenu或TrackPopupMenuex。否则,菜单将不会
当用户单击菜单外或窗口外
创建菜单(如果可见)。如果当前窗口是一个孩子
窗口,您必须将(顶级)父窗口设置为前景
窗口
ShowContextMenu()
“其他并且需要在托盘图标内设置图标(当前为空)。”
请右键单击您的图像,选择属性,然后检查“构建操作”是否为
”内容。请检查您的图像路径是否正确。
SetForegroundWindow(_hwnd);
uint nCmd = TrackPopupMenu(hMenu, 0x100, cursorPos.X, cursorPos.Y, 0, _hwnd, IntPtr.Zero);
PostMessage(_hwnd, 0x0000, IntPtr.Zero, IntPtr.Zero);