|
本帖最后由 shiy720 于 2025-3-5 19:47 编辑
在WPF中通过Windows API实现系统托盘图标需调用Shell_NotifyIcon及相关Win32函数,以下是具体步骤
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- namespace Wxapp.Common.win32
- {
- public class TrayIcon
- {
- private const int WM_USER = 0x0400;
- private const int WM_LBUTTONDBLCLK = 0x0203;
- private const int WM_RBUTTONUP = 0x0205;
- private const int NIM_ADD = 0x00000000;
- private const int NIM_MODIFY = 0x00000001;
- private const int NIM_DELETE = 0x00000002;
- private const int NIF_MESSAGE = 0x00000001;
- private const int NIF_ICON = 0x00000002;
- private const int NIF_TIP = 0x00000004;
- [StructLayout(LayoutKind.Sequential)]
- private struct NOTIFYICONDATA
- {
- public int cbSize;
- public IntPtr hWnd;
- public int uID;
- public int uFlags;
- public int uCallbackMessage;
- public IntPtr hIcon;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string szTip;
- }
- [DllImport("shell32.dll", SetLastError = true)]
- private static extern bool Shell_NotifyIcon(int dwMessage, ref NOTIFYICONDATA lpData);
- [DllImport("user32.dll", SetLastError = true)]
- private static extern IntPtr LoadIcon(IntPtr hInstance, IntPtr lpIconName);
- [DllImport("user32.dll", SetLastError = true)]
- private static extern bool DestroyIcon(IntPtr hIcon);
- #region 创建右键菜单
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern IntPtr CreatePopupMenu();
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern int TrackPopupMenuEx(IntPtr hMenu, uint uFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern bool DestroyMenu(IntPtr hMenu);
- #endregion
- #region 获取鼠标右键位置
- // 定义 POINT 结构体
- [StructLayout(LayoutKind.Sequential)]
- public struct POINT
- {
- public int X;
- public int Y;
- }
- // 定义 Win32 API 函数
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool GetCursorPos(out POINT lpPoint);
- #endregion
- #region 定义事件 与 保护方法
- public event Action OnShowWindow;
- protected virtual void ShowWindow() => OnShowWindow?.Invoke();
- public event Action OnCloseWindow;
- protected virtual void CloseWindow() => OnCloseWindow?.Invoke();
- public event Action<Exception> Error;
- protected virtual void OnError(Exception ex) => Error?.Invoke(ex);
- #endregion
- private NOTIFYICONDATA notifyIconData;
- private IntPtr hIcon;
- private IntPtr popupMenu;
- private nint wHandle;
- public TrayIcon(nint _wHandle)
- {
- this.wHandle = _wHandle;
- }
- /// <summary>
- /// 初始化托盘图标结构 :ml-citation{ref="1" data="citationList"}
- /// </summary>
- /// <param name="Title"></param>
- public void InitializeTrayIcon(string Title= "My Application")
- {
- notifyIconData = new NOTIFYICONDATA();
- notifyIconData.cbSize = Marshal.SizeOf(notifyIconData);
- notifyIconData.hWnd = wHandle;
- notifyIconData.uID = 0;
- notifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
- notifyIconData.uCallbackMessage = WM_USER + 1;
- hIcon = LoadIcon(IntPtr.Zero, new IntPtr(32512)); // 使用默认图标
- notifyIconData.hIcon = hIcon;
- notifyIconData.szTip = Title;
- Shell_NotifyIcon(NIM_ADD, ref notifyIconData);
- }
-
- public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
- {
- if (msg == notifyIconData.uCallbackMessage)
- {
- switch ((int)lParam)
- {
- case WM_LBUTTONDBLCLK:
- this.ShowWindow();
- break;
- case WM_RBUTTONUP:
- this.showPopupMenu(hwnd);
- break;
- }
- }
- return IntPtr.Zero;
- }
- public void createMenu()
- {
- popupMenu = CreatePopupMenu();
- AppendMenu(popupMenu, 0x00000000, 1, "展示");
- AppendMenu(popupMenu, 0x00000000, 2, "退出");
- }
- private void showPopupMenu(IntPtr hwnd) {
- POINT point;
- GetCursorPos(out point);
- // 显示右键菜单
- int command = TrackPopupMenuEx(popupMenu, 0x00000100, point.X, point.Y, hwnd, IntPtr.Zero);
- Debug.WriteLine($">>>>>>> : {command}");
- if (command > 0)
- CloseWindow();
- }
- /// <summary>
- /// 销毁菜单和图潘图标
- /// </summary>
- /// <param name="e"></param>
- public void Destroy(EventArgs e)
- {
- DestroyMenu(popupMenu);
- Shell_NotifyIcon(NIM_DELETE, ref notifyIconData);
- }
- }
- }
复制代码
调用方法
- var windowHandle = new WindowInteropHelper(this).Handle;
- trayIcon = new TrayIcon(windowHandle);
- HwndSource source = HwndSource.FromHwnd(windowHandle);
- source.AddHook(trayIcon.WndProc);
- trayIcon.InitializeTrayIcon( );
- trayIcon.OnShowWindow += () => {
- MessageBox.Show("haha");
- };
- trayIcon.createMenu();
复制代码
|
|