前几天有网友问.NET CF中怎么实现NotifyIcon,我这才知道原来.NET CF并没有提供NotifyIcon控件。
 于是偶想PC上可以用Shell_NotifyIcon和MessageWindow来实现托盘图标,只是不知道.NET CF支持不支持这两个东东了。仔细看了一下.NET CF中可疑的命名空间,没想到在Microsoft.WindowsCE.Forms命名空间里面竟然有一个MessageWindow 类,太好了,只剩下一个Shell_NotifyIcon 函数了。接着 在Window CE的SDK的帮助文件里,又发现Window CE Platform API已经包含了Shell_NotifyIcon函数。两大“主料”都齐了,只剩下锅了。
 先看一下MessageWindow类,这个类提供了 WndProc 方法,用于处理窗口消息,并公开了可能传递给本机窗口函数的有效窗口句柄。要使用它,派生一个新类,并重写的 WndProc 方法,这样才能截获特定的窗口消息。这里主要用来处理click事件。
 Shell_NotifyIcon的用法如下:
[DllImport("coredll.dll")]
internal static extern int Shell_NotifyIcon(int dwMessage, ref NOTIFYICONDATA pnid);
其中,NOTIFYICONDATA结构如下:
struct NOTIFYICONDATA
{
 int cbSize;
 IntPtr hWnd;
 uint uID;
 uint uFlags;
 uint uCallbackMessage;
 IntPtr hIcon;
}
 Pnid参数的生命需要注意,是按引用传递的,因为Shell_NotifyIcon 需要一个指向 NOTIFYICONDATA 结构的指针。
 hWnd是用来接收任务栏中图标单击消息的窗口的句柄。
运行示例的时候由于窗体最大化,挡住了任务栏,把窗体最小化之后就能看到托盘图标了。(效果图片竟然贴不上来,改天再贴吧)
该类和示例的下载地址:http://www.cnblogs.com/Files/ttinfo/NotifyIconCf.rar
下面是NotifyIcon类的实现,别忘了引用Microsoft.WindowsCE.Forms。注意Add方法提供了不同的重载形式,具体请参看注释:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace NotifyClient
{
 /**//// 
 /// 智能设备托盘图标类
 /// 
 public class NotifyIcon
 {
 //单击事件
 public event System.EventHandler Click;
 private MyMessageWindow messageWindow;
 private int uID = 5000;
 private System.Drawing.Icon _Icon;
 
 public NotifyIcon()
 {
 messageWindow = new MyMessageWindow(this);
 messageWindow.uID = uID;
 }
 public System.Drawing.Icon Icon
 {
 set
 {
 _Icon = value;
 }
 }
 
 ~NotifyIcon()
 {
 Remove();
 }
 /**//// 
 /// 添加托盘图标
 /// 
 /// icon文件的有效句柄
 public void Add(IntPtr hIcon)
 {
 NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, hIcon);
 }
 /**//// 
 /// 添加托盘图标
 /// 
 /// 编译之后的资源文件中的icon资源名称,如“#201547”
 public void Add(string IconRes)
 {
 IntPtr hIcon = LoadIcon(GetModuleHandle(null), IconRes);
 NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, hIcon);
 }
 /**//// 
 /// 添加托盘图标
 /// 
 /// icon文件
 public void Add(System.Drawing.Icon icon)
 {
 NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, icon.Handle);
 }
 /**//// 
 /// 添加托盘图标;icon为属性中的icon
 /// 
 public void Add()
 {
 if (_Icon != null)
 {
 NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, _Icon.Handle);
 }
 }
 public void Remove()
 {
 NotifyMessage(messageWindow.Hwnd, NIM_DELETE, (uint)uID, IntPtr.Zero);
 }
 public void Modify(IntPtr hIcon)
 {
 NotifyMessage(messageWindow.Hwnd, NIM_MODIFY, (uint)uID, hIcon);
 }
 
 private void NotifyMessage(IntPtr hwnd, int dwMessage, uint uID, IntPtr hIcon)
 {
 NOTIFYICONDATA notdata = new NOTIFYICONDATA();
 notdata.cbSize = 152;
 notdata.hIcon = hIcon;
 notdata.hWnd = hwnd;
 notdata.uCallbackMessage = WM_NOTIFY_TRAY;
 notdata.uFlags = NIF_MESSAGE | NIF_ICON;
 notdata.uID = uID;
 int ret = Shell_NotifyIcon(dwMessage, ref notdata);
 }
 API#region API 
 //定义消息常量
 const int NIF_MESSAGE = 0x00000001;
 const int NIF_ICON = 0x00000002;
 internal const int WM_LBUTTONDOWN = 0x0201; 
 internal const int NIM_ADD = 0x00000000;
 internal const int NIM_MODIFY = 0x00000001;
 internal const int NIM_DELETE = 0x00000002;
 //自定义消息
 internal const int WM_NOTIFY_TRAY = 0x0400 + 2001;
 
 internal struct NOTIFYICONDATA
 {
 internal int cbSize;
 internal IntPtr hWnd;
 internal uint uID;
 internal uint uFlags;
 internal uint uCallbackMessage;
 internal IntPtr hIcon; 
 }
 [DllImport("coredll.dll")]
 internal static extern int Shell_NotifyIcon(
 int dwMessage, ref NOTIFYICONDATA pnid);
 [DllImport("coredll.dll")]
 internal static extern int SetForegroundWindow(IntPtr hWnd);
 [DllImport("coredll.dll")]
 internal static extern int ShowWindow(
 IntPtr hWnd,
 int nCmdShow);
 [DllImport("coredll.dll")]
 internal static extern IntPtr GetFocus();
 [DllImport("coredll.dll")]
 internal static extern IntPtr LoadIcon(IntPtr hInst, string IconName);
 [DllImport("coredll.dll")]
 internal static extern IntPtr GetModuleHandle(String lpModuleName);
 #endregion
 MessageWindow#region MessageWindow
 internal class MyMessageWindow : Microsoft.WindowsCE.Forms.MessageWindow
 {
 
 private int _uID = 0;
 private NotifyIcon notifyIcon;
 
 public MyMessageWindow(NotifyIcon notIcon)
 {
 notifyIcon = notIcon;
 }
 public int uID
 {
 set
 {
 _uID = value;
 }
 }
 protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message msg)
 {
 if (msg.Msg == WM_NOTIFY_TRAY)
 {
 if ((int)msg.LParam == WM_LBUTTONDOWN)
 {
 if ((int)msg.WParam == _uID)
 {
 
 if (notifyIcon.Click != null)
 notifyIcon.Click(notifyIcon, null);
 }
 }
 }
 }
 }
 #endregion
 }
}