1 public class InnerClass: Form 2 { 3 private Shell_NotifyIconEx servicesClass = null; // 接受主CLASS 的实例句柄 4 internal InnerClass(Shell_NotifyIconEx _servicesClass) 5 { 6 servicesClass = _servicesClass; 7 } 8 9 private const int WM_LBUTTONDOWN = 0x0201; // 左键10 private const int WM_RBUTTONDOWN = 0x204; // 右键11 private const int WM_MBUTTONDOWN = 0x207; // 中键12 13 [DllImport("user32.dll", EntryPoint = "TrackPopupMenu")]14 private static extern int TrackPopupMenu( // c# 和vb.net 好象没有了随地popup 了,只要请它老人家出马了15 IntPtr hMenu,16 int wFlags,17 int x,18 int y,19 int nReserved,20 IntPtr hwnd,21 ref RECT lprc22 );23 24 [StructLayout(LayoutKind.Sequential)]25 private struct RECT26 { // 上面那位用的结构,表示前弹出菜单可用的一个范围大小(一般是全屏幕都让它用,留着搞游戏或视频对话之类的朋友指定菜单可用的范围)27 internal int Left;28 internal int Top;29 internal int Right;30 internal int Bottom;31 }32 33 protected override void WndProc(ref Message msg)34 {35 if (msg.Msg == servicesClass.WM_NOTIFY_TRAY)36 { // 如果消息相符37 if ((int)msg.WParam == servicesClass.uID)38 { // 并且消息的WParam 相符39 MouseButtons mb =MouseButtons.None;40 if ((int)msg.LParam == WM_LBUTTONDOWN)41 { //如果点击的是左键42 mb =MouseButtons.Left;43 }44 else if ((int)msg.LParam == WM_MBUTTONDOWN)45 { //中键46 mb =MouseButtons.Middle;47 }48 else if ((int)msg.LParam == WM_RBUTTONDOWN)49 { //右键50 if (servicesClass.contextMenuHwnd != IntPtr.Zero)51 { //如果有定义过菜单关联52 RECT r = new RECT();53 r.Left = Screen.PrimaryScreen.WorkingArea.Left;54 r.Right =Screen.PrimaryScreen.WorkingArea.Right;55 r.Top =Screen.PrimaryScreen.WorkingArea.Top;56 r.Bottom =Screen.PrimaryScreen.WorkingArea.Right;57 58 TrackPopupMenu(59 servicesClass.contextMenuHwnd,60 2,61 Cursor.Position.X,62 Cursor.Position.Y,63 0,64 servicesClass.formHwnd,65 ref r66 );67 }68 else69 { //如果没有定义过菜单关联70 mb =MouseButtons.Right;71 }72 }73 74 if (mb !=MouseButtons.None && servicesClass._delegateOfCallBack != null)75 {76 servicesClass._delegateOfCallBack(mb); // 执行回调77 return;78 }79 }80 }81 82 base.WndProc(ref msg);83 }84 }
1 public class Shell_NotifyIconEx 2 { 3 /// <summary> 4 /// ArLi, last fix: 2003.9.12, reference: ArLi.CommonPrj Lib @ 5 /// </summary> 6 public static readonly System.Version myVersion = new System.Version(1, 2); //版本声明 7 8 private readonly InnerClass formTmp = null; // 这个很重要,不能放在构造里,因为它必须和此实例同等生存期才不会被中止消息循环 9 private readonly IntPtr formTmpHwnd = IntPtr.Zero; // 这是上一行的句柄 10 private readonly bool VersionOk = false; // 这是一个由VersionPass 返回的属性,它允许开发者检测当前机子的Shell32.dll(可能在win95 或未知平台上版本) 合适此组,不符则用.net 自己的notifyicon 11 private bool forgetDelNotifyBox = false; // 这是一个私有标志,它允许开发者在程序退出时忘记调用DelNotifyBox 来清除图标时会自动在析构里清掉它。 12 13 internal IntPtr formHwnd = IntPtr.Zero; // 这是调用此组件的主窗口句柄(当前实例有效,可多个icon 不冲突) 14 internal IntPtr contextMenuHwnd = IntPtr.Zero; // 这是菜单的句柄(当前实例有效,可多个icon 不冲突) 15 16 internal delegate void delegateOfCallBack(System.Windows.Forms.MouseButtons mb); 17 internal delegateOfCallBack _delegateOfCallBack = null; 18 19 public Shell_NotifyIconEx() // 构造 20 { 21 WM_NOTIFY_TRAY += 1; // 消息ID +1,避免多个ICON 消息处理冲突 22 uID += 1; // 同上 23 formTmp = new InnerClass(this); // 新实例一个消息循环 24 formTmpHwnd = formTmp.Handle; // 新实例句柄 25 VersionOk = this.GetShell32VersionInfo() >= 5; // 版本是否合适,此组件由于重点在气泡提示,它要求Shell32.dll 5.0(ie 5.0) 以上 26 } 27 28 ~Shell_NotifyIconEx() 29 { // 析构 30 if (forgetDelNotifyBox) this.DelNotifyBox(); //如果开发者忘记则清理icon 31 } 32 33 #region API_Consts 34 internal readonly int WM_NOTIFY_TRAY = 0x0400 + 2001; //readonly 表示只在构造可付值 35 internal readonly int uID = 5000; 36 37 // 常数定义,有VC 的可以参见 shellapi.h 38 private const int NIIF_NONE = 0x00; 39 private const int NIIF_INFO = 0x01; 40 private const int NIIF_WARNING = 0x02; 41 private const int NIIF_ERROR = 0x03; 42 43 private const int NIF_MESSAGE = 0x01; 44 private const int NIF_ICON = 0x02; 45 private const int NIF_TIP = 0x04; 46 private const int NIF_STATE = 0x08; 47 private const int NIF_INFO = 0x10; 48 49 private const int NIM_ADD = 0x00; 50 private const int NIM_MODIFY = 0x01; 51 private const int NIM_DELETE = 0x02; 52 private const int NIM_SETFOCUS = 0x03; 53 private const int NIM_SETVERSION = 0x04; 54 55 private const int NIS_HIDDEN = 0x01; 56 private const int NIS_SHAREDICON = 0x02; 57 58 private const int NOTIFYICON_OLDVERSION = 0x00; 59 private const int NOTIFYICON_VERSION = 0x03; 60 61 [DllImport("shell32.dll", EntryPoint = "Shell_NotifyIcon")] 62 private static extern bool Shell_NotifyIcon( // 这位是主角 63 int dwMessage, 64 ref NOTIFYICONDATA lpData 65 ); 66 67 /// <summary> 68 /// 此API 的作用是当 this.focus() 无效时可以考虑使用,效果很好 69 /// </summary> 70 /// <param name="hwnd">this.Handle, 当前窗体句柄</param> 71 [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")] 72 public static extern int SetForegroundWindow( 73 IntPtr hwnd 74 ); 75 76 [StructLayout(LayoutKind.Sequential)] 77 private struct NOTIFYICONDATA 78 { // 主角用的结构 79 internal int cbSize; 80 internal IntPtr hwnd; 81 internal int uID; 82 internal int uFlags; 83 internal int uCallbackMessage; 84 internal IntPtr hIcon; 85 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x80)] 86 internal string szTip; 87 internal int dwState; // 这里往下几个是 5.0 的精华 88 internal int dwStateMask; 89 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0xFF)] 90 internal string szInfo; 91 internal int uTimeoutAndVersion; 92 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)] 93 internal string szInfoTitle; 94 internal int dwInfoFlags; 95 } 96
没有评论:
发表评论