http://blog.csdn.net/pgshow/article/details/7526168
这里为了给同学写一个小工具,要用到系统托盘的功能,编程偶才刚入门,所以花了3个小时才调试好。趁热打铁,把学到的具体内容分享下。
要用到的函数是Shell_NotifyIcon,VC里需要包含头文件ShellApi.h。
函数就是Shell_NotifyIcon,原型如下:
BOOL Shell_NotifyIcon(DWORD dwMessage,NOTIFYICONDATA lpdata);
首先是第一个参数dwMessage,可以取下面两个值:
NIM_ADD //这个会添加一个图标到系统托盘处
NIM_DELETE //我们用这个删除系统托盘处的图片
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;
看似很复杂,不过我们只会用到几个参数而已,下面我会说明的:
使用步骤:
1.先定义一个全局的变量:
NOTIFYICONDATA nid
2.然后在适当的位置对nid进行初始化,我是在主窗口的 while (GetMessage (&msg, NULL, 0, 0)) 语句之前初始化的。
- nid.cbSize = sizeof(NOTIFYICONDATA); //初始化结构的大小
- nid.hWnd = hwnd; //指定接收托盘消息的句柄
- nid.uID = IDI_ICON1; //指定托盘图标的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_ICON1)); //设置图标的句柄
- _tcscpy(nid.szTip,TEXT("TimeWork正在工作!\r\n点击打开主界面")); //设置鼠标移上托盘图标时的提示信息 //_tcscpy是tchar.h里定义的宏
完成了上面的设置,就可以调用了。
3.我们将在最小化窗口消息里调用 Shell_NotifyIcon(NIM_ADD, &nid) 将图标设置到系统托盘。
- 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(hwnd,SW_HIDE);
- Shell_NotifyIcon(NIM_ADD, &nid);
- return TRUE;
- }
在自定义的 WM_IAWENTRAY 消息里面判断鼠标是否点击,并调用 ShowWindow(hwnd, SW_SHOWNORMAL) 显示主窗口。
- case WM_IAWENTRAY:
- if(wParam == IDI_ICON1){
- if(lParam == WM_LBUTTONDOWN){
- ShowWindow(hDlg, SW_SHOWNORMAL);
- return TRUE;
- }
- }
- return FALSE;
其中消息的wParam参数为指定的图标ID,lParam参数为事件类型,示例里只接收了WM_LBUTTONDOWN事件,即鼠标左键点击事件!
完整的代码如下:
- #include <windows.h>
- #include <tchar.h>
- #include "ShellAPI.h"
- #include "resource.h"
- #define WM_IAWENTRAY WM_USER+5 //系统托盘的自定义消息
- //定义全局变量
- HINSTANCE g_hInst;
- NOTIFYICONDATA nid;
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- g_hInst = hInstance; //获取该程序实例句柄
- static TCHAR szAppName[] = TEXT ("TimeWork") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wndclass ;
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = WndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szAppName ;
- if (!RegisterClass (&wndclass))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"),
- szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- hwnd = CreateWindow (szAppName, // window class name
- TEXT ("一个Shell_NotifyIcon实例程序"), // window caption
- WS_OVERLAPPEDWINDOW, // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL) ; // creation parameters
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- //初始化NOTIFYICONDATA结构
- nid.cbSize=sizeof(NOTIFYICONDATA);
- nid.hWnd=hwnd;
- nid.uID=IDI_ICON1;
- nid.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;
- nid.uCallbackMessage=WM_IAWENTRAY;
- nid.hIcon=LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));
- _tcscpy(nid.szTip,TEXT("TimeWork正在工作!\r\n点击打开主界面")); //_tcscpy是windows宏,需包含头文件tchar.h
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc ;
- PAINTSTRUCT ps ;
- RECT rect ;
- switch (message)
- {
- case WM_CREATE:
- return 0 ;
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- GetClientRect (hwnd, &rect) ;
- DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
- DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
- EndPaint (hwnd, &ps) ;
- return 0 ;
- case WM_IAWENTRAY:
- if(wParam == IDI_ICON1){
- if(lParam == WM_LBUTTONDOWN){
- //还可以在这个地方加入一个菜单,鼠标右键单击时显示
- ShowWindow(hwnd, SW_SHOWNORMAL);
- return TRUE;
- }
- }
- return FALSE;
- case WM_SYSCOMMAND:
- switch(wParam)
- {
- case SC_CLOSE:
- DestroyWindow(hwnd);
- PostQuitMessage(0);
- break;
- case SC_MINIMIZE:
- ShowWindow(hwnd,SW_HIDE);
- Shell_NotifyIcon(NIM_ADD,&nid); //最小化时隐藏窗口并设置系统托盘
- break;
- }
- return 0;
- case WM_DESTROY:
- Shell_NotifyIcon(NIM_DELETE,&nid);
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lPar