我正在尝试制作一个包括托盘图标的winui3应用程序。关闭应用程序时,它应该转到系统托盘并在后台运行。当我右键单击托盘图标时,应该出现两个菜单选项 - “打开”和“退出”。单击“打开”时,应用程序应重新打开,然后单击“退出”时,应用程序应关闭。

问题描述 投票:0回答:1

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

中,在处理托盘和菜单项时,我从未收到消息enter image description hereWM_Command

WM_Command

WM_SysCommand

。我还希望当我单击其他任何地方并需要在托盘图标内设置图标(当前为空)时,菜单也会消失。我无法运行H.notifyicon,目前不想使用它,因为它不完整。 有人可以帮助我如何在winui3中制作适当的系统托盘图标? 根据TrackPopupMenuDocument 如果您在uflags参数中指定tpm_returncmd(100),则返回 值是用户选择的项目的菜单项目标识符。 因此,您可以处理用户的点击结果。

“我也希望菜单在我单击任何地方时消失”

winui-3 systray
1个回答
0
投票

显示通知图标的上下文菜单,当前窗口 在申请通话之前必须是前景窗口 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);

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.