在Pocket PC的Today界面上的任务栏加入你的应用程序图标

以前, 看见很多程序有这个功能,觉得这个功能太好了.并且很cool.

只需要在Today界面上点击这个图标,你的应用程序就会弹出来,实在是一个不错的功能.相当于桌面上的最大化和最小化.

相信在桌面上解决这个问题实在是easy,本质上是加个托盘图标.

切换到正题上来.

如何加入?查了一下.net cf,你会发现没有提供相应的类以及函数.不过不要紧,如果有Windows APIWindows相关编程经验,你会注意到下面的问题还是相对简单的.

查找一下Windows提供的API,你会发现一个一个结构NOTIFYICONDATA.让我们看看这个结构干什么用的.下面的信息来自于MSDN:

NOTIFYICONDATA结构包含了系统处理任务栏状态区域信息的信息.

此结构为:

typedef struct _NOTIFYICONDATA { 
  DWORD cbSize;
//结构的大小
  HWND hWnd; //于任务栏图标相关的窗体句柄
  UINT uID; //任务栏图标的应用程序定义的标志符.
  UINT uFlags; //包含有效数据的标记
  UINT uCallbackMessage; //回调消息的标志符
  HICON hIcon; //图标的句柄
  WCHAR szTip[64]; //tips
} NOTIFYICONDATA, *PNOTIFYICONDATA; 

看了这个结构,就知道大概意思了.注意到此结构需要窗体的句柄,图标的句柄,以及事件的标志.有了这3个家伙,我们就可以实现了.

那么哪一个函数调用此结构呢?答案是Shell_NotifyIcon,看看Shell_NotifyIcon的定义(MSDN):

WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(
  DWORD dwMessage, 
  PNOTIFYICONDATA pnid 
);

此方法有2个参数,前者指定发送的消息值它有3种消息: NIM_ADD,NIM_MODIFY,NIM_DELETE.这些就是对任务栏图标的操作.第二个参数就是NOTIFYICONDATA的指针形式.

怎么样,知道怎么做了吧.

好了,说了这么多开始实现它吧.

首先写写NotifyIcon类吧,它用来增加和删除任务栏的图标.代码如下:

/// <summary>
    
/// IconNotify class, is used to add/remove the icon in Today screen.Also can send a notification to application.
    
/// </summary>
    public class IconNotify
    {
        
//Declare click event
        public event System.EventHandler Click;

        
private WindowSink windowSink;
        
private int uID = 5000;

        
//Constructor
        public IconNotify()
        {
            
//Create instance of the MessageWindow subclass
            windowSink = new WindowSink(this);
            windowSink.uID 
= uID;
        }

        
//Destructor
        ~IconNotify()
        {
            Remove();            
        }

        
public void Add(IntPtr hIcon)
        {
            TrayMessage(windowSink.Hwnd, NIM_ADD, (
uint)uID, hIcon);
        }

        
public void Remove()
        {
        
            TrayMessage(windowSink.Hwnd, NIM_DELETE, (
uint)uID, IntPtr.Zero);
        }

        
public void Modify(IntPtr hIcon)
        {
            
            TrayMessage(windowSink.Hwnd, NIM_MODIFY, (
uint)uID, hIcon);

        }

        
private void TrayMessage(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);
        } 

        
#region API Declarations

        
internal const int WM_LBUTTONDOWN = 0x0201;
        
//User defined message
        internal const int WM_NOTIFY_TRAY = 0x0400 + 2001;

        
internal const int NIM_ADD       =  0x00000000;
        
internal const int NIM_MODIFY    =  0x00000001;
        
internal const int NIM_DELETE    =  0x00000002;

        
const int NIF_MESSAGE   =  0x00000001;
        
const int NIF_ICON      =  0x00000002;

        
/// <summary>
        
/// Contains information that the system needs to process taskbar status area messages.
        
/// </summary>
        internal struct NOTIFYICONDATA 
        { 
            
/// <summary>
            
/// Size of this structure, in bytes.
            
/// </summary>
            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();

        
#endregion
}

 

但是看了上面的代码,总觉得少了一点什么东西似的,,那就是消息的触发.那么点击了任务栏的图标之后如何触发事件呢?首先我们得实现Tray Icon(托盘图标)事件,在此事件里,需要更进一步的实现WM_LBUTTONDOWN事件.但是如何实现了呢?幸运的是.net cf提供了一个Microsoft.WindowsCE.Forms.Message,它提供了托管消息与非托管消息的交互.这样就好办了.代码如下:

#region WindowSink

        
internal class WindowSink : Microsoft.WindowsCE.Forms.MessageWindow
        {
            
//Private members
            private int m_uID = 0;
            
private IconNotify notifyIcon;

            
//Constructor
            public WindowSink(IconNotify notIcon)
            {
                notifyIcon 
= notIcon;    
            }
            
            
public int uID
            {
                
set
                {
                    m_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 == m_uID)
                        {
                            
//If somebody hooked, raise the event
                            if (notifyIcon.Click != null)
                                notifyIcon.Click(notifyIcon, 
null);
        
                        }
                    }    
                }
                                
            }
        }
        
#endregion
简单吧,,^_^

 FAQ:
1)如何得到窗体的句柄?
   调用FindWindow()方法.具体参见MSDN.
2)如何调用Icon的句柄?
 调用LoadIcon().具体参见MSDN.
3)如何加入点击消息?
   实现NotifyIcon.Click事件.
4)如何得到里面的常数?
   2种方法:1是直接根据MSDN在VC下的头文件里找.2是调用API Text Viewer工具.不过以上2种方法都需要你安装VS98.

参考:http://www.microsoft.com/downloads/details.aspx?FamilyId=5A8384C0-34A5-47D1-BB50-E5E261288AE3&displaylang=en
以上大部分代码来自此.

posted @ 2006-05-22 12:46  张太国  阅读(4100)  评论(1编辑  收藏  举报