找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 10|回复: 0

[wpf] 写了个在wpf中使用Windows API实现系统托盘图标的类

[复制链接]
发表于 7 天前 | 显示全部楼层 |阅读模式
本帖最后由 shiy720 于 2025-3-5 19:47 编辑

在WPF中通过Windows API实现系统托盘图标需调用Shell_NotifyIcon及相关Win32函数,以下是具体步骤

  1. using System.Diagnostics;
  2. using System.Runtime.InteropServices;
  3. namespace Wxapp.Common.win32
  4. {
  5.     public class TrayIcon
  6.     {
  7.         private const int WM_USER = 0x0400;
  8.         private const int WM_LBUTTONDBLCLK = 0x0203;
  9.         private const int WM_RBUTTONUP = 0x0205;
  10.         private const int NIM_ADD = 0x00000000;
  11.         private const int NIM_MODIFY = 0x00000001;
  12.         private const int NIM_DELETE = 0x00000002;
  13.         private const int NIF_MESSAGE = 0x00000001;
  14.         private const int NIF_ICON = 0x00000002;
  15.         private const int NIF_TIP = 0x00000004;

  16.         [StructLayout(LayoutKind.Sequential)]
  17.         private struct NOTIFYICONDATA
  18.         {
  19.             public int cbSize;
  20.             public IntPtr hWnd;
  21.             public int uID;
  22.             public int uFlags;
  23.             public int uCallbackMessage;
  24.             public IntPtr hIcon;
  25.             [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
  26.             public string szTip;
  27.         }

  28.         [DllImport("shell32.dll", SetLastError = true)]
  29.         private static extern bool Shell_NotifyIcon(int dwMessage, ref NOTIFYICONDATA lpData);

  30.         [DllImport("user32.dll", SetLastError = true)]
  31.         private static extern IntPtr LoadIcon(IntPtr hInstance, IntPtr lpIconName);

  32.         [DllImport("user32.dll", SetLastError = true)]
  33.         private static extern bool DestroyIcon(IntPtr hIcon);

  34.         #region 创建右键菜单


  35.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  36.         private static extern IntPtr CreatePopupMenu();

  37.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  38.         public static extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);

  39.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  40.         private static extern int TrackPopupMenuEx(IntPtr hMenu, uint uFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);


  41.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  42.         private static extern bool DestroyMenu(IntPtr hMenu);
  43.         #endregion

  44.         #region 获取鼠标右键位置
  45.         // 定义 POINT 结构体
  46.         [StructLayout(LayoutKind.Sequential)]
  47.         public struct POINT
  48.         {
  49.             public int X;
  50.             public int Y;
  51.         }

  52.         // 定义 Win32 API 函数
  53.         [DllImport("user32.dll")]
  54.         [return: MarshalAs(UnmanagedType.Bool)]
  55.         private static extern bool GetCursorPos(out POINT lpPoint);

  56.         #endregion

  57.         #region 定义事件 与 保护方法
  58.         public event Action OnShowWindow;
  59.         protected virtual void ShowWindow() => OnShowWindow?.Invoke();

  60.         public event Action OnCloseWindow;
  61.         protected virtual void CloseWindow() => OnCloseWindow?.Invoke();


  62.         public event Action<Exception> Error;
  63.         protected virtual void OnError(Exception ex) => Error?.Invoke(ex);

  64.         #endregion

  65.         private NOTIFYICONDATA notifyIconData;
  66.         private IntPtr hIcon;
  67.         private IntPtr popupMenu;
  68.         private nint wHandle;
  69.         public TrayIcon(nint _wHandle)
  70.         {
  71.             this.wHandle = _wHandle;

  72.         }
  73.         /// <summary>
  74.         /// 初始化托盘图标结构 ‌:ml-citation{ref="1" data="citationList"}
  75.         /// </summary>
  76.         /// <param name="Title"></param>
  77.         public void InitializeTrayIcon(string Title= "My Application")
  78.         {
  79.             notifyIconData = new NOTIFYICONDATA();
  80.             notifyIconData.cbSize = Marshal.SizeOf(notifyIconData);
  81.             notifyIconData.hWnd =   wHandle;
  82.             notifyIconData.uID = 0;
  83.             notifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  84.             notifyIconData.uCallbackMessage = WM_USER + 1;
  85.             hIcon = LoadIcon(IntPtr.Zero, new IntPtr(32512)); // 使用默认图标
  86.             notifyIconData.hIcon = hIcon;
  87.             notifyIconData.szTip = Title;

  88.             Shell_NotifyIcon(NIM_ADD, ref notifyIconData);
  89.         }
  90.          
  91.         public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  92.         {
  93.             if (msg == notifyIconData.uCallbackMessage)
  94.             {
  95.                 switch ((int)lParam)
  96.                 {
  97.                     case WM_LBUTTONDBLCLK:
  98.                         this.ShowWindow();
  99.                         break;
  100.                     case WM_RBUTTONUP:
  101.                         this.showPopupMenu(hwnd);
  102.                         break;
  103.                 }
  104.             }
  105.             return IntPtr.Zero;
  106.         }
  107.         public void createMenu()
  108.         {
  109.             popupMenu = CreatePopupMenu();
  110.             AppendMenu(popupMenu, 0x00000000, 1, "展示");
  111.             AppendMenu(popupMenu, 0x00000000, 2, "退出");
  112.         }
  113.         private void showPopupMenu(IntPtr hwnd) {
  114.             POINT point;
  115.             GetCursorPos(out point);
  116.             // 显示右键菜单
  117.             int command = TrackPopupMenuEx(popupMenu, 0x00000100, point.X, point.Y, hwnd, IntPtr.Zero);
  118.             Debug.WriteLine($">>>>>>> : {command}");
  119.             if (command > 0)
  120.                 CloseWindow();
  121.         }
  122.         /// <summary>
  123.         /// 销毁菜单和图潘图标
  124.         /// </summary>
  125.         /// <param name="e"></param>
  126.         public void Destroy(EventArgs e)
  127.         {
  128.             DestroyMenu(popupMenu);
  129.             Shell_NotifyIcon(NIM_DELETE, ref notifyIconData);
  130.         }
  131.     }
  132. }
复制代码


调用方法

  1.             var windowHandle = new WindowInteropHelper(this).Handle;
  2.             trayIcon = new TrayIcon(windowHandle);
  3.             HwndSource source = HwndSource.FromHwnd(windowHandle);
  4.             source.AddHook(trayIcon.WndProc);
  5.             trayIcon.InitializeTrayIcon( );
  6.             trayIcon.OnShowWindow += () => {
  7.                 MessageBox.Show("haha");
  8.             };
  9.             trayIcon.createMenu();
复制代码



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|西兴社区 ( 蜀ICP备2022005627号 )|网站地图

GMT+8, 2025-3-12 19:40 , Processed in 0.160371 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表