很久没有弄这个了,差点了,见朋友的博客有个Delphi版的,于是自己也想弄一个VC的出来!
要实现系统托盘图标,关键在于一个系统函数和一个数据结构。
函数就是Shell_NotifyIcon,原型如下:
BOOL Shell_NotifyIcon(DWORD dwMessage,NOTIFYICONDATA lpdata);
而数据结构就是NOTIFYICONDATA了,呵呵,具体如下:
typedef struct _NOTIFYICONDATA {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
TCHAR szTip[64];
DWORD dwState;
DWORD dwStateMask;
TCHAR szInfo[256];
union {
UINT uTimeout;
UINT uVersion;
};
TCHAR szInfoTitle[64];
DWORD dwInfoFlags;
GUID guidItem;
HICON hBalloonIcon;
} NOTIFYICONDATA, *PNOTIFYICONDATA;
具体的解释,大家还是查查MSDN吧,这里不多说了!主要用到的几个是:
1、由于Shell_NotifyIcon是定义在shellapi.h里的,所以程序里需要包含上。
2、Shell_NotifyIcon的第一个参数取值:
A)、NIM_ADD //这个就是添加一个系统托盘图标了
B)、NIM_DELETE //这个是在退出时删除系统托盘图标了
3、对Shell_NotifyIcon的第2个参数,也即NOTIFYICONDATA结构的设置了:
A)、先定义一个全局的变量:NOTIFYICONDATA nid
B)、然后在适当的位置对其进行初始化:
对于对话框程序,一般在WM_INITDIALOG里消息初始,不过我这里是用CreateDialog来创建对话框的,所以在主程序WinMain里初始化:
nid.cbSize=sizeof(NOTIFYICONDATA); //初始化结构的大小
nid.hWnd=g_hWnd; //指定接收托盘消息的句柄
nid.uID=IDI_TRAY; //指定托盘图标的ID,呵呵
nid.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP; //设定结构里有效的位置
//NIF_ICON: 指定hIcon是有效的,(这里设定自定义系统托盘图标必须的)
//NIF_MESSAGE: 指定uCallbackMessage是有效的,用于程序接收来自托盘图标的消息,需要自定义一个消息
//NIF_TIP: 指定szTip是有效的,功能是当鼠标移动到图标上时,显示提示信息
nid.uCallbackMessage=WM_IAWENTRAY; //自定义的消息,
//#define WM_IAWENTRAY WM_USER+5
nid.hIcon=LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TRAY)); //设置图标的句柄
strcpy(nid.szTip,"测试系统托盘图标,呵呵\r\n点击打开主界面"); //设置提示信息
完成了上面的设置,现在就是开始调用了!
这里示例,是设定系统最小化按钮为隐藏到系统托盘,退出时则删除系统托盘!
如:
case WM_DESTROY:
Shell_NotifyIcon(NIM_DELETE,&nid);
return TRUE;
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_CLOSE:
DestroyWindow(hDlg);
PostQuitMessage(0);
return TRUE;
case SC_MINIMIZE:
ShowWindow(g_hWnd,SW_HIDE);
Shell_NotifyIcon(NIM_ADD,&nid);
return TRUE;
}
这里只所以没有在SC_CLOSE消息里直接删除托盘图标,而是因为在WM_DESTROY里处理会更好!
如果是在SC_CLOSE里直接处理,则会出现程序退出时,图标还在,只有当鼠标移过图标时则会完全不见!
大家可以测试一下,^&^……
而程序要接收来自系统托盘的消息,则是通过我们上面的定义的消息:
case WM_IAWENTRAY:
if(wParam==IDI_TRAY){
if(lParam==WM_LBUTTONDOWN){
ShowWindow(hDlg,SW_SHOWNORMAL);
return TRUE;
}
}
return FALSE;
其中消息的wParam参数为指定的图标ID,lParam参数为事件类型,示例里只接收了WM_LBUTTONDOWN事件,即鼠标左键点击事件!
完整的的代码示例如下:
#include
#include
#include"resource.h"
#define WM_IAWENTRAY WM_USER+5
HINSTANCE g_hInst;
HWND g_hWnd;
NOTIFYICONDATA nid;
INT_PTR CALLBACK MainDlgProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR lpCmdLine,int nShowCmd)
{
g_hInst=hInstance;
g_hWnd=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,MainDlgProc);
ShowWindow(g_hWnd,nShowCmd);
nid.cbSize=sizeof(NOTIFYICONDATA);
nid.hWnd=g_hWnd;
nid.uID=IDI_TRAY;
nid.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage=WM_IAWENTRAY;
nid.hIcon=LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TRAY));
strcpy(nid.szTip,"测试系统托盘图标,呵呵\r\n点击打开主界面"); //
MSG uMsg;
while(GetMessage(&uMsg,NULL,0,0)){
TranslateMessage(&uMsg);
DispatchMessage(&uMsg);
}
return 0;
}
INT_PTR CALLBACK MainDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg){
case WM_INITDIALOG:
{
HICON hIcon=LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TRAY));
SendMessage(hDlg,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
SendMessage(hDlg,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
SetDlgItemText(hDlg,IDC_INFO,TEXT("Write By Iawen --2009.02.03"));
return TRUE;
}
case WM_IAWENTRAY:
if(wParam==IDI_TRAY){
if(lParam==WM_LBUTTONDOWN){
ShowWindow(hDlg,SW_SHOWNORMAL);
return TRUE;
}
}
return FALSE;
case WM_DESTROY:
Shell_NotifyIcon(NIM_DELETE,&nid);
return TRUE;
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_CLOSE:
DestroyWindow(hDlg);
PostQuitMessage(0);
return TRUE;
case SC_MINIMIZE:
ShowWindow(g_hWnd,SW_HIDE);
Shell_NotifyIcon(NIM_ADD,&nid);
return TRUE;
}
}
return FALSE;
}
附件为完整的程序示例工程:
TrayIcon.rar