2003的NotifyIcon没有气泡提示功能,所以扩展了一个新的,能达到2005的NotifyIcon的同样功能,并且提供了两个新的功能。
静态方法 FindNotifyIcon 在系统托盘里查找提示文本相同的托盘句柄,以便以向它发送消息。
事件 DoWndProc 托盘WndProc时触发。
下面是程序清单:
比如使用它可以使程序只运行一个实例:
静态方法 FindNotifyIcon 在系统托盘里查找提示文本相同的托盘句柄,以便以向它发送消息。
事件 DoWndProc 托盘WndProc时触发。
下面是程序清单:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace FaibClass.Windows.Forms
{
public sealed class NotifyIcon : Component
{
private bool added;
private ContextMenu contextMenu;
private bool doubleClick;
private ToolTipIcon balloonTipIcon;
private string balloonTipText;
private string balloonTipTitle;
private IntPtr handle = IntPtr.Zero;
private Icon icon;
private int id;
private static int nextId = 0;
private string text;
private bool visible = true;
private NotifyIconNativeWindow window;
private static int WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
private const int WM_USER = 0x400;
private const int WM_TRAYMOUSEMESSAGE = 2048;
private const int WM_MOUSEMOVE = 0x200;
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_LBUTTONUP = 0x202;
private const int WM_LBUTTONDBLCLK = 0x203;
private const int WM_RBUTTONDOWN = 0x204;
private const int WM_RBUTTONUP = 0x205;
private const int WM_RBUTTONDBLCLK = 0x206;
private const int WM_MBUTTONDOWN = 0x207;
private const int WM_MBUTTONUP = 0x208;
private const int WM_MBUTTONDBLCLK = 0x209;
private const int NIN_BALLOONSHOW = 0x402;
private const int NIN_BALLOONHIDE = 0x403;
private const int NIN_BALLOONTIMEOUT = 0x404;
private const int NIN_BALLOONUSERCLICK = 0x405;
private const int READ_CONTROL = 0x20000;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int STANDARD_RIGHTS_READ = READ_CONTROL;
private const int STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
private const int STANDARD_RIGHTS_ALL = 0x1F0000;
private const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
private const int SYNCHRONIZE = 0x100000;
private const int PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;
private const int PROCESS_TERMINATE = 0x1;
private const int PROCESS_VM_OPERATION = 0x8;
private const int PROCESS_VM_READ = 0x10;
private const int PROCESS_VM_WRITE = 0x20;
private const int MEM_RESERVE = 0x2000;
private const int MEM_COMMIT = 0x1000;
private const int MEM_RELEASE = 0x8000;
private const int PAGE_READWRITE = 0x4;
private const int TB_BUTTONCOUNT = (WM_USER + 24);
private const int TB_HIDEBUTTON = (WM_USER + 4);
private const int TB_GETBUTTON = (WM_USER + 23);
private const int TB_GETBITMAP = (WM_USER + 44);
private const int TB_DELETEBUTTON = (WM_USER + 22);
private const int TB_ADDBUTTONS = (WM_USER + 20);
private const int TB_INSERTBUTTON = (WM_USER + 21);
private const int TB_ISBUTTONHIDDEN = (WM_USER + 12);
private const int ILD_NORMAL = 0x0;
private const int TPM_NONOTIFY = 0x80;
枚举
结构
Win32 API 引用
public event EventHandler Click;
public event EventHandler DoubleClick;
public event MouseEventHandler MouseDown;
public event MouseEventHandler MouseMove;
public event MouseEventHandler MouseUp;
public event EventHandler BalloonTipClicked;
public event EventHandler BalloonTipClosed;
public event EventHandler BalloonTipShown;
public event WndProcEventHandler DoWndProc;
public NotifyIcon()
{
icon = null;
text = "";
id = 0;
added = false;
window = null;
contextMenu = null;
doubleClick = false;
id = ++nextId;
window = new NotifyIconNativeWindow(this);
//UpdateIcon(visible);
}
public NotifyIcon(IContainer container) : this()
{
container.Add(this);
}
属性
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (window != null)
{
icon = null;
Text = "";
UpdateIcon(false);
window.DestroyHandle();
window = null;
contextMenu = null;
}
}
else if ((window != null) && (window.Handle != IntPtr.Zero))
{
PostMessage(new HandleRef(window, window.Handle), 16, 0, 0);
window.ReleaseHandle();
}
base.Dispose(disposing);
}
private void OnBalloonTipClicked()
{
if (BalloonTipClicked != null)
BalloonTipClicked(this, EventArgs.Empty);
}
private void OnBalloonTipClosed()
{
if (BalloonTipClosed != null)
BalloonTipClosed(this, EventArgs.Empty);
}
private void OnBalloonTipShown()
{
if (BalloonTipShown != null)
BalloonTipShown(this, EventArgs.Empty);
}
private void OnClick(EventArgs e)
{
if (Click != null)
Click(this, e);
}
private void OnDoubleClick(EventArgs e)
{
if (DoubleClick != null)
DoubleClick(this, e);
}
private void OnMouseDown(MouseEventArgs e)
{
if (MouseDown != null)
MouseDown(this, e);
}
private void OnMouseMove(MouseEventArgs e)
{
if (MouseMove != null)
MouseMove(this, e);
}
private void OnMouseUp(MouseEventArgs e)
{
if (MouseUp != null)
MouseUp(this, e);
}
private bool OnDoWndProc(ref Message m)
{
if (DoWndProc != null)
return DoWndProc(this, ref m);
return true;
}
private void ShowContextMenu()
{
if (contextMenu != null)
{
POINT pt = new POINT();
GetCursorPos(ref pt);
SetForegroundWindow(new HandleRef(window, window.Handle));
contextMenu.GetType().InvokeMember("OnPopup",
BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance,
null, contextMenu, new Object[] {new EventArgs()});
TrackPopupMenuEx(new HandleRef(contextMenu, contextMenu.Handle), TPM_NONOTIFY, pt.x, pt.y, new HandleRef(window, window.Handle), null);
PostMessage(new HandleRef(window, window.Handle), 0, IntPtr.Zero, IntPtr.Zero);
}
}
private void UpdateIcon(bool showIconInTray)
{
lock (this)
{
if (!base.DesignMode)
{
window.LockReference(showIconInTray);
NotifyIconData pnid = new NotifyIconData();
pnid.uCallbackMessage = 0x800;
pnid.uFlags = NotifyFlags.Message;
if (showIconInTray && (window.Handle == IntPtr.Zero))
{
window.CreateHandle(new CreateParams());
}
pnid.cbSize =Marshal.SizeOf(pnid);
pnid.hWnd = window.Handle;
pnid.uID = id;
pnid.hIcon = IntPtr.Zero;
pnid.szTip = null;
if (icon != null)
{
pnid.uFlags |= NotifyFlags.Icon;
pnid.hIcon = icon.Handle;
}
pnid.uFlags |= NotifyFlags.Tip;
pnid.szTip = text;
if (showIconInTray && (icon != null))
{
if (!added)
{
Shell_NotifyIcon(NotifyCommand.Add, ref pnid);
added = true;
}
else
{
Shell_NotifyIcon(NotifyCommand.Modify, ref pnid);
}
}
else if (added)
{
Shell_NotifyIcon(NotifyCommand.Delete, ref pnid);
added = false;
}
}
}
}
public static IntPtr FindNotifyIcon(string TipTitle)
{
if(TipTitle.Length == 0)return IntPtr.Zero;
IntPtr pid = IntPtr.Zero;
IntPtr ipHandle = IntPtr.Zero; //图标句柄
IntPtr lTextAdr = IntPtr.Zero; //文本内存地址
IntPtr ipTemp = FindWindow("Shell_TrayWnd", null);
//找到托盘
ipTemp = FindWindowEx(ipTemp, IntPtr.Zero, "TrayNotifyWnd", null);
ipTemp = FindWindowEx(ipTemp, IntPtr.Zero, "SysPager", null);
IntPtr ipTray = FindWindowEx(ipTemp, IntPtr.Zero, "ToolbarWindow32", null);
GetWindowThreadProcessId(ipTray, ref pid);
if(pid.Equals(0))return ipHandle;
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, IntPtr.Zero, pid);
IntPtr lAddress = VirtualAllocEx(hProcess, 0, 4096, MEM_COMMIT, PAGE_READWRITE);
//得到图标个数
int lButton = SendMessage(ipTray, TB_BUTTONCOUNT, 0, 0);
for(int i = 0; i < lButton; i++)
{
SendMessage(ipTray, TB_GETBUTTON, i, lAddress);
//读文本地址
ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 16), ref lTextAdr, 4, 0);
if(!lTextAdr.Equals(-1))
{
byte[] buff = new byte[1024];
//读文本
ReadProcessMemory(hProcess, lTextAdr, buff, 1024, 0);
string title = System.Text.ASCIIEncoding.Unicode.GetString(buff);
// 从字符0处截断
int nullindex = title.IndexOf("\0");
if(nullindex > 0)
{
title = title.Substring(0, nullindex);
}
//ReadProcessMemory(hProcess, lAddress, ref ipButtonID, 4, 0);
//判断是不是要找的图标
if(title.Equals(TipTitle))
{
IntPtr ipHandleAdr = IntPtr.Zero;
//读句柄地址
ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 12), ref ipHandleAdr, 4, 0);
ReadProcessMemory(hProcess, ipHandleAdr, ref ipHandle, 4, 0);
break;
}
}
}
VirtualFreeEx(hProcess, lAddress, 4096, MEM_RELEASE);
CloseHandle(hProcess);
return ipHandle;
}
public void ShowBalloonTip(int timeout)
{
ShowBalloonTip(balloonTipTitle, balloonTipText, balloonTipIcon, timeout);
}
public void ShowBalloonTip(string tipTitle, string tipText, ToolTipIcon tipIcon, int timeout)
{
if (timeout < 0)
{
throw new ArgumentOutOfRangeException("timeout", "超时时间不错误");
}
if (tipText == null || tipText.Length == 0)
{
throw new ArgumentException("显示的信息不能为空");
}
if (added && !base.DesignMode)
{
NotifyIconData pnid = new NotifyIconData();
if (window.Handle == IntPtr.Zero)
{
//创建窗体
window.CreateHandle(new CreateParams());
}
pnid.cbSize =Marshal.SizeOf(pnid);
pnid.hWnd = window.Handle;
pnid.uID = id;
pnid.uFlags = NotifyFlags.Info;
pnid.uTimeoutOrVersion = timeout;
pnid.szInfoTitle = tipTitle;
pnid.szInfo = tipText;
pnid.dwInfoFlags = tipIcon;
Shell_NotifyIcon(NotifyCommand.Modify, ref pnid);
}
//延时后更新图标
System.Threading.Thread.Sleep(50);
UpdateIcon(visible);
}
private void WmMouseDown(ref Message m, MouseButtons button, int clicks)
{
if (clicks == 2) //双击
{
OnDoubleClick(EventArgs.Empty);
doubleClick = true;
}
OnMouseDown(new MouseEventArgs(button, clicks, 0, 0, 0));
}
private void WmMouseMove(ref Message m)
{
OnMouseMove(new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
}
private void WmMouseUp(ref Message m, MouseButtons button)
{
OnMouseUp(new MouseEventArgs(button, 0, 0, 0, 0));
if (!doubleClick)
{
OnClick(EventArgs.Empty);
}
doubleClick = false;
}
private void WmTaskbarCreated(ref Message m)
{
added = false;
UpdateIcon(visible);
}
private void WndProc(ref Message msg)
{
if(!OnDoWndProc(ref msg))return; //中断消息
Console.WriteLine(msg.Msg);
switch (msg.Msg)
{
case 0x2b://WM_DRAWITEM
break;
case 0x2c://WM_MEASUREITEM
break;
case 0x111://WM_COMMAND
if (IntPtr.Zero == msg.LParam)
{
Type typeCmd = typeof(Form).Assembly.GetType("System.Windows.Forms.Command");
MethodInfo methodDispId = typeCmd.GetMethod("DispatchID", BindingFlags.Static | BindingFlags.Public);
int code = ((int)msg.WParam) & 0xffff;
bool res = (bool)methodDispId.Invoke(null, new object[]{code});
break;
}
window.DefWndProc(ref msg);
return;
case 0x800://WM_TRAYMOUSEMESSAGE:
switch ((int)msg.LParam)
{
case WM_MOUSEMOVE:
this.WmMouseMove(ref msg);
return;
case WM_LBUTTONDOWN:
this.WmMouseDown(ref msg, MouseButtons.Left, 1);
return;
case WM_LBUTTONUP:
this.WmMouseUp(ref msg, MouseButtons.Left);
return;
case WM_LBUTTONDBLCLK:
this.WmMouseDown(ref msg, MouseButtons.Left, 2);
return;
case WM_RBUTTONDOWN:
this.WmMouseDown(ref msg, MouseButtons.Right, 1);
return;
case WM_RBUTTONUP:
if (this.contextMenu != null)
{
this.ShowContextMenu();
}
this.WmMouseUp(ref msg, MouseButtons.Right);
return;
case WM_RBUTTONDBLCLK:
this.WmMouseDown(ref msg, MouseButtons.Right, 2);
return;
case WM_MBUTTONDOWN:
this.WmMouseDown(ref msg, MouseButtons.Middle, 1);
return;
case WM_MBUTTONUP:
this.WmMouseUp(ref msg, MouseButtons.Middle);
return;
case WM_MBUTTONDBLCLK:
this.WmMouseDown(ref msg, MouseButtons.Middle, 2);
return;
case NIN_BALLOONSHOW:
this.OnBalloonTipShown();
return;
case NIN_BALLOONHIDE:
this.OnBalloonTipClosed();
return;
case NIN_BALLOONTIMEOUT:
this.OnBalloonTipClosed();
return;
case NIN_BALLOONUSERCLICK:
this.OnBalloonTipClicked();
return;
}
return;
default:
if (msg.Msg == WM_TASKBARCREATED)
{
WmTaskbarCreated(ref msg);
}
window.DefWndProc(ref msg);
break;
}
}
private class NotifyIconNativeWindow : NativeWindow
{
internal NotifyIcon reference;
private GCHandle rootRef;
internal NotifyIconNativeWindow(NotifyIcon control)
{
reference = control;
}
~ NotifyIconNativeWindow()
{
if (base.Handle != IntPtr.Zero)
{
PostMessage(new HandleRef(this, base.Handle), 16, 0, 0);
}
}
public void LockReference(bool locked)
{
if (locked)
{
if (!rootRef.IsAllocated)
{
rootRef = GCHandle.Alloc(reference, GCHandleType.Normal);
}
}
else if (rootRef.IsAllocated)
{
rootRef.Free();
}
}
protected override void OnThreadException(Exception e)
{
Application.OnThreadException(e);
}
protected override void WndProc(ref Message m)
{
reference.WndProc(ref m);
}
}
}
[Flags]
public enum ToolTipIcon
{
None = 0,
Info = 1,
Warning = 2,
Error = 3
}
public delegate bool WndProcEventHandler (object sender, ref Message m);
}
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace FaibClass.Windows.Forms
{
public sealed class NotifyIcon : Component
{
private bool added;
private ContextMenu contextMenu;
private bool doubleClick;
private ToolTipIcon balloonTipIcon;
private string balloonTipText;
private string balloonTipTitle;
private IntPtr handle = IntPtr.Zero;
private Icon icon;
private int id;
private static int nextId = 0;
private string text;
private bool visible = true;
private NotifyIconNativeWindow window;
private static int WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
private const int WM_USER = 0x400;
private const int WM_TRAYMOUSEMESSAGE = 2048;
private const int WM_MOUSEMOVE = 0x200;
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_LBUTTONUP = 0x202;
private const int WM_LBUTTONDBLCLK = 0x203;
private const int WM_RBUTTONDOWN = 0x204;
private const int WM_RBUTTONUP = 0x205;
private const int WM_RBUTTONDBLCLK = 0x206;
private const int WM_MBUTTONDOWN = 0x207;
private const int WM_MBUTTONUP = 0x208;
private const int WM_MBUTTONDBLCLK = 0x209;
private const int NIN_BALLOONSHOW = 0x402;
private const int NIN_BALLOONHIDE = 0x403;
private const int NIN_BALLOONTIMEOUT = 0x404;
private const int NIN_BALLOONUSERCLICK = 0x405;
private const int READ_CONTROL = 0x20000;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int STANDARD_RIGHTS_READ = READ_CONTROL;
private const int STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
private const int STANDARD_RIGHTS_ALL = 0x1F0000;
private const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
private const int SYNCHRONIZE = 0x100000;
private const int PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF;
private const int PROCESS_TERMINATE = 0x1;
private const int PROCESS_VM_OPERATION = 0x8;
private const int PROCESS_VM_READ = 0x10;
private const int PROCESS_VM_WRITE = 0x20;
private const int MEM_RESERVE = 0x2000;
private const int MEM_COMMIT = 0x1000;
private const int MEM_RELEASE = 0x8000;
private const int PAGE_READWRITE = 0x4;
private const int TB_BUTTONCOUNT = (WM_USER + 24);
private const int TB_HIDEBUTTON = (WM_USER + 4);
private const int TB_GETBUTTON = (WM_USER + 23);
private const int TB_GETBITMAP = (WM_USER + 44);
private const int TB_DELETEBUTTON = (WM_USER + 22);
private const int TB_ADDBUTTONS = (WM_USER + 20);
private const int TB_INSERTBUTTON = (WM_USER + 21);
private const int TB_ISBUTTONHIDDEN = (WM_USER + 12);
private const int ILD_NORMAL = 0x0;
private const int TPM_NONOTIFY = 0x80;
枚举
结构
Win32 API 引用
public event EventHandler Click;
public event EventHandler DoubleClick;
public event MouseEventHandler MouseDown;
public event MouseEventHandler MouseMove;
public event MouseEventHandler MouseUp;
public event EventHandler BalloonTipClicked;
public event EventHandler BalloonTipClosed;
public event EventHandler BalloonTipShown;
public event WndProcEventHandler DoWndProc;
public NotifyIcon()
{
icon = null;
text = "";
id = 0;
added = false;
window = null;
contextMenu = null;
doubleClick = false;
id = ++nextId;
window = new NotifyIconNativeWindow(this);
//UpdateIcon(visible);
}
public NotifyIcon(IContainer container) : this()
{
container.Add(this);
}
属性
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (window != null)
{
icon = null;
Text = "";
UpdateIcon(false);
window.DestroyHandle();
window = null;
contextMenu = null;
}
}
else if ((window != null) && (window.Handle != IntPtr.Zero))
{
PostMessage(new HandleRef(window, window.Handle), 16, 0, 0);
window.ReleaseHandle();
}
base.Dispose(disposing);
}
private void OnBalloonTipClicked()
{
if (BalloonTipClicked != null)
BalloonTipClicked(this, EventArgs.Empty);
}
private void OnBalloonTipClosed()
{
if (BalloonTipClosed != null)
BalloonTipClosed(this, EventArgs.Empty);
}
private void OnBalloonTipShown()
{
if (BalloonTipShown != null)
BalloonTipShown(this, EventArgs.Empty);
}
private void OnClick(EventArgs e)
{
if (Click != null)
Click(this, e);
}
private void OnDoubleClick(EventArgs e)
{
if (DoubleClick != null)
DoubleClick(this, e);
}
private void OnMouseDown(MouseEventArgs e)
{
if (MouseDown != null)
MouseDown(this, e);
}
private void OnMouseMove(MouseEventArgs e)
{
if (MouseMove != null)
MouseMove(this, e);
}
private void OnMouseUp(MouseEventArgs e)
{
if (MouseUp != null)
MouseUp(this, e);
}
private bool OnDoWndProc(ref Message m)
{
if (DoWndProc != null)
return DoWndProc(this, ref m);
return true;
}
private void ShowContextMenu()
{
if (contextMenu != null)
{
POINT pt = new POINT();
GetCursorPos(ref pt);
SetForegroundWindow(new HandleRef(window, window.Handle));
contextMenu.GetType().InvokeMember("OnPopup",
BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance,
null, contextMenu, new Object[] {new EventArgs()});
TrackPopupMenuEx(new HandleRef(contextMenu, contextMenu.Handle), TPM_NONOTIFY, pt.x, pt.y, new HandleRef(window, window.Handle), null);
PostMessage(new HandleRef(window, window.Handle), 0, IntPtr.Zero, IntPtr.Zero);
}
}
private void UpdateIcon(bool showIconInTray)
{
lock (this)
{
if (!base.DesignMode)
{
window.LockReference(showIconInTray);
NotifyIconData pnid = new NotifyIconData();
pnid.uCallbackMessage = 0x800;
pnid.uFlags = NotifyFlags.Message;
if (showIconInTray && (window.Handle == IntPtr.Zero))
{
window.CreateHandle(new CreateParams());
}
pnid.cbSize =Marshal.SizeOf(pnid);
pnid.hWnd = window.Handle;
pnid.uID = id;
pnid.hIcon = IntPtr.Zero;
pnid.szTip = null;
if (icon != null)
{
pnid.uFlags |= NotifyFlags.Icon;
pnid.hIcon = icon.Handle;
}
pnid.uFlags |= NotifyFlags.Tip;
pnid.szTip = text;
if (showIconInTray && (icon != null))
{
if (!added)
{
Shell_NotifyIcon(NotifyCommand.Add, ref pnid);
added = true;
}
else
{
Shell_NotifyIcon(NotifyCommand.Modify, ref pnid);
}
}
else if (added)
{
Shell_NotifyIcon(NotifyCommand.Delete, ref pnid);
added = false;
}
}
}
}
public static IntPtr FindNotifyIcon(string TipTitle)
{
if(TipTitle.Length == 0)return IntPtr.Zero;
IntPtr pid = IntPtr.Zero;
IntPtr ipHandle = IntPtr.Zero; //图标句柄
IntPtr lTextAdr = IntPtr.Zero; //文本内存地址
IntPtr ipTemp = FindWindow("Shell_TrayWnd", null);
//找到托盘
ipTemp = FindWindowEx(ipTemp, IntPtr.Zero, "TrayNotifyWnd", null);
ipTemp = FindWindowEx(ipTemp, IntPtr.Zero, "SysPager", null);
IntPtr ipTray = FindWindowEx(ipTemp, IntPtr.Zero, "ToolbarWindow32", null);
GetWindowThreadProcessId(ipTray, ref pid);
if(pid.Equals(0))return ipHandle;
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, IntPtr.Zero, pid);
IntPtr lAddress = VirtualAllocEx(hProcess, 0, 4096, MEM_COMMIT, PAGE_READWRITE);
//得到图标个数
int lButton = SendMessage(ipTray, TB_BUTTONCOUNT, 0, 0);
for(int i = 0; i < lButton; i++)
{
SendMessage(ipTray, TB_GETBUTTON, i, lAddress);
//读文本地址
ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 16), ref lTextAdr, 4, 0);
if(!lTextAdr.Equals(-1))
{
byte[] buff = new byte[1024];
//读文本
ReadProcessMemory(hProcess, lTextAdr, buff, 1024, 0);
string title = System.Text.ASCIIEncoding.Unicode.GetString(buff);
// 从字符0处截断
int nullindex = title.IndexOf("\0");
if(nullindex > 0)
{
title = title.Substring(0, nullindex);
}
//ReadProcessMemory(hProcess, lAddress, ref ipButtonID, 4, 0);
//判断是不是要找的图标
if(title.Equals(TipTitle))
{
IntPtr ipHandleAdr = IntPtr.Zero;
//读句柄地址
ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 12), ref ipHandleAdr, 4, 0);
ReadProcessMemory(hProcess, ipHandleAdr, ref ipHandle, 4, 0);
break;
}
}
}
VirtualFreeEx(hProcess, lAddress, 4096, MEM_RELEASE);
CloseHandle(hProcess);
return ipHandle;
}
public void ShowBalloonTip(int timeout)
{
ShowBalloonTip(balloonTipTitle, balloonTipText, balloonTipIcon, timeout);
}
public void ShowBalloonTip(string tipTitle, string tipText, ToolTipIcon tipIcon, int timeout)
{
if (timeout < 0)
{
throw new ArgumentOutOfRangeException("timeout", "超时时间不错误");
}
if (tipText == null || tipText.Length == 0)
{
throw new ArgumentException("显示的信息不能为空");
}
if (added && !base.DesignMode)
{
NotifyIconData pnid = new NotifyIconData();
if (window.Handle == IntPtr.Zero)
{
//创建窗体
window.CreateHandle(new CreateParams());
}
pnid.cbSize =Marshal.SizeOf(pnid);
pnid.hWnd = window.Handle;
pnid.uID = id;
pnid.uFlags = NotifyFlags.Info;
pnid.uTimeoutOrVersion = timeout;
pnid.szInfoTitle = tipTitle;
pnid.szInfo = tipText;
pnid.dwInfoFlags = tipIcon;
Shell_NotifyIcon(NotifyCommand.Modify, ref pnid);
}
//延时后更新图标
System.Threading.Thread.Sleep(50);
UpdateIcon(visible);
}
private void WmMouseDown(ref Message m, MouseButtons button, int clicks)
{
if (clicks == 2) //双击
{
OnDoubleClick(EventArgs.Empty);
doubleClick = true;
}
OnMouseDown(new MouseEventArgs(button, clicks, 0, 0, 0));
}
private void WmMouseMove(ref Message m)
{
OnMouseMove(new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
}
private void WmMouseUp(ref Message m, MouseButtons button)
{
OnMouseUp(new MouseEventArgs(button, 0, 0, 0, 0));
if (!doubleClick)
{
OnClick(EventArgs.Empty);
}
doubleClick = false;
}
private void WmTaskbarCreated(ref Message m)
{
added = false;
UpdateIcon(visible);
}
private void WndProc(ref Message msg)
{
if(!OnDoWndProc(ref msg))return; //中断消息
Console.WriteLine(msg.Msg);
switch (msg.Msg)
{
case 0x2b://WM_DRAWITEM
break;
case 0x2c://WM_MEASUREITEM
break;
case 0x111://WM_COMMAND
if (IntPtr.Zero == msg.LParam)
{
Type typeCmd = typeof(Form).Assembly.GetType("System.Windows.Forms.Command");
MethodInfo methodDispId = typeCmd.GetMethod("DispatchID", BindingFlags.Static | BindingFlags.Public);
int code = ((int)msg.WParam) & 0xffff;
bool res = (bool)methodDispId.Invoke(null, new object[]{code});
break;
}
window.DefWndProc(ref msg);
return;
case 0x800://WM_TRAYMOUSEMESSAGE:
switch ((int)msg.LParam)
{
case WM_MOUSEMOVE:
this.WmMouseMove(ref msg);
return;
case WM_LBUTTONDOWN:
this.WmMouseDown(ref msg, MouseButtons.Left, 1);
return;
case WM_LBUTTONUP:
this.WmMouseUp(ref msg, MouseButtons.Left);
return;
case WM_LBUTTONDBLCLK:
this.WmMouseDown(ref msg, MouseButtons.Left, 2);
return;
case WM_RBUTTONDOWN:
this.WmMouseDown(ref msg, MouseButtons.Right, 1);
return;
case WM_RBUTTONUP:
if (this.contextMenu != null)
{
this.ShowContextMenu();
}
this.WmMouseUp(ref msg, MouseButtons.Right);
return;
case WM_RBUTTONDBLCLK:
this.WmMouseDown(ref msg, MouseButtons.Right, 2);
return;
case WM_MBUTTONDOWN:
this.WmMouseDown(ref msg, MouseButtons.Middle, 1);
return;
case WM_MBUTTONUP:
this.WmMouseUp(ref msg, MouseButtons.Middle);
return;
case WM_MBUTTONDBLCLK:
this.WmMouseDown(ref msg, MouseButtons.Middle, 2);
return;
case NIN_BALLOONSHOW:
this.OnBalloonTipShown();
return;
case NIN_BALLOONHIDE:
this.OnBalloonTipClosed();
return;
case NIN_BALLOONTIMEOUT:
this.OnBalloonTipClosed();
return;
case NIN_BALLOONUSERCLICK:
this.OnBalloonTipClicked();
return;
}
return;
default:
if (msg.Msg == WM_TASKBARCREATED)
{
WmTaskbarCreated(ref msg);
}
window.DefWndProc(ref msg);
break;
}
}
private class NotifyIconNativeWindow : NativeWindow
{
internal NotifyIcon reference;
private GCHandle rootRef;
internal NotifyIconNativeWindow(NotifyIcon control)
{
reference = control;
}
~ NotifyIconNativeWindow()
{
if (base.Handle != IntPtr.Zero)
{
PostMessage(new HandleRef(this, base.Handle), 16, 0, 0);
}
}
public void LockReference(bool locked)
{
if (locked)
{
if (!rootRef.IsAllocated)
{
rootRef = GCHandle.Alloc(reference, GCHandleType.Normal);
}
}
else if (rootRef.IsAllocated)
{
rootRef.Free();
}
}
protected override void OnThreadException(Exception e)
{
Application.OnThreadException(e);
}
protected override void WndProc(ref Message m)
{
reference.WndProc(ref m);
}
}
}
[Flags]
public enum ToolTipIcon
{
None = 0,
Info = 1,
Warning = 2,
Error = 3
}
public delegate bool WndProcEventHandler (object sender, ref Message m);
}
比如使用它可以使程序只运行一个实例:
[STAThread]
static void Main(params string[] pars)
{
//确保只有一个实例运行
Process current = Process.GetCurrentProcess();
Process[] ps = Process.GetProcessesByName(current.ProcessName);
foreach(Process process in ps)
{
if(!process.Id.Equals(current.Id))
{
IntPtr nti = FbSoft.Assistant.Controls.NotifyIcon.FindNotifyIcon("NotifyIcon标题");
if(nti != IntPtr.Zero)
{
//向托盘发送自定消息 WM_USER + 0x33;
Win32.SendMessage(nti, 0x400 + 0x33, 0, 0);
}
Application.Exit();
return;
}
}
frmMain里触发事件:
static void Main(params string[] pars)
{
//确保只有一个实例运行
Process current = Process.GetCurrentProcess();
Process[] ps = Process.GetProcessesByName(current.ProcessName);
foreach(Process process in ps)
{
if(!process.Id.Equals(current.Id))
{
IntPtr nti = FbSoft.Assistant.Controls.NotifyIcon.FindNotifyIcon("NotifyIcon标题");
if(nti != IntPtr.Zero)
{
//向托盘发送自定消息 WM_USER + 0x33;
Win32.SendMessage(nti, 0x400 + 0x33, 0, 0);
}
Application.Exit();
return;
}
}
private bool ntiMain_DoWndProc(object sender, ref System.Windows.Forms.Message m)
{
if(m.Msg == 0x400 + 0x33)
{
ntiMain_DoubleClick(null, null);
return false;
}
return true;
}
private void ntiMain_DoubleClick(object sender, System.EventArgs e)
{
if(Visible)return;
Thread.Sleep(100);
isLoad = true;
if(!ShowInTaskbar)
{
ShowInTaskbar = true;
}
isLoad = false;
Win32.SetForegroundWindow(Handle);
Win32.SetActiveWindow(Handle);
WindowState = FormWindowState.Maximized;
Show();
}
{
if(m.Msg == 0x400 + 0x33)
{
ntiMain_DoubleClick(null, null);
return false;
}
return true;
}
private void ntiMain_DoubleClick(object sender, System.EventArgs e)
{
if(Visible)return;
Thread.Sleep(100);
isLoad = true;
if(!ShowInTaskbar)
{
ShowInTaskbar = true;
}
isLoad = false;
Win32.SetForegroundWindow(Handle);
Win32.SetActiveWindow(Handle);
WindowState = FormWindowState.Maximized;
Show();
}