windows API 创建系统托盘图标

系统托盘在我们使用的程序中很普遍,下面我们来看一个很不错的例子,使用Win32 API实现,对理解系统托盘有些帮助。

  1. #include <windows.h>  
  2. #define IDR_PAUSE 12  
  3. #define IDR_START 13  
  4. /* 
  5. #include <shellapi.h> 
  6. #pragma   comment(lib,   "shell32.lib")  
  7. */  
  8. LPCTSTR szAppName = TEXT("服务程序");  
  9. LPCTSTR szWndName = TEXT("服务程序");  
  10. HMENU hmenu;//菜单句柄  
  11.   
  12. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  13. {  
  14.     NOTIFYICONDATA nid;  
  15.     UINT WM_TASKBARCREATED;  
  16.     POINT pt;//用于接收鼠标坐标  
  17.     int xx;//用于接收菜单选项返回值  
  18.   
  19.     // 不要修改TaskbarCreated,这是系统任务栏自定义的消息  
  20.     WM_TASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));  
  21.     switch (message)  
  22.     {  
  23.     case WM_CREATE://窗口创建时候的消息.  
  24.         nid.cbSize = sizeof(nid);  
  25.         nid.hWnd = hwnd;  
  26.         nid.uID = 0;  
  27.         nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;  
  28.         nid.uCallbackMessage = WM_USER;  
  29.         nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);  
  30.         lstrcpy(nid.szTip, szAppName);  
  31.         Shell_NotifyIcon(NIM_ADD, &nid);  
  32.         hmenu=CreatePopupMenu();//生成菜单  
  33.         AppendMenu(hmenu,MF_STRING,IDR_PAUSE,"暂停服务");//为菜单添加两个选项  
  34.         AppendMenu(hmenu,MF_STRING,IDR_START,"恢复服务");  
  35.         break;  
  36.     case WM_USER://连续使用该程序时候的消息.  
  37.         if (lParam == WM_LBUTTONDOWN)  
  38.             MessageBox(hwnd, TEXT("Win32 API 实现系统托盘程序,双击托盘可以退出!"), szAppName, MB_OK);  
  39.         if (lParam == WM_LBUTTONDBLCLK)//双击托盘的消息,退出.  
  40.             SendMessage(hwnd, WM_CLOSE, wParam, lParam);  
  41.         if (lParam == WM_RBUTTONDOWN)  
  42.         {  
  43.             GetCursorPos(&pt);//取鼠标坐标  
  44.             ::SetForegroundWindow(hwnd);//解决在菜单外单击左键菜单不消失的问题  
  45.             EnableMenuItem(hmenu,IDR_PAUSE,MF_GRAYED);//让菜单中的某一项变灰  
  46.             xx=TrackPopupMenu(hmenu,TPM_RETURNCMD,pt.x,pt.y,NULL,hwnd,NULL);//显示菜单并获取选项ID  
  47.             if(xx==IDR_PAUSE) MessageBox(hwnd, TEXT("111"), szAppName, MB_OK);  
  48.             if(xx==IDR_START) MessageBox(hwnd, TEXT("222"), szAppName, MB_OK);  
  49.             if(xx==0) PostMessage(hwnd,WM_LBUTTONDOWN,NULL,NULL);  
  50.             //MessageBox(hwnd, TEXT("右键"), szAppName, MB_OK);  
  51.         }  
  52.         break;  
  53.     case WM_DESTROY://窗口销毁时候的消息.  
  54.         Shell_NotifyIcon(NIM_DELETE, &nid);  
  55.         PostQuitMessage(0);  
  56.         break;  
  57.     default:  
  58.         /* 
  59.         * 防止当Explorer.exe 崩溃以后,程序在系统系统托盘中的图标就消失 
  60.         * 
  61.         * 原理:Explorer.exe 重新载入后会重建系统任务栏。当系统任务栏建立的时候会向系统内所有 
  62.         * 注册接收TaskbarCreated 消息的顶级窗口发送一条消息,我们只需要捕捉这个消息,并重建系 
  63.         * 统托盘的图标即可。 
  64.         */  
  65.         if (message == WM_TASKBARCREATED)  
  66.             SendMessage(hwnd, WM_CREATE, wParam, lParam);  
  67.         break;  
  68.     }  
  69.     return DefWindowProc(hwnd, message, wParam, lParam);  
  70. }  
  71.   
  72. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,  
  73.                    LPSTR szCmdLine, int iCmdShow)  
  74. {  
  75.     HWND hwnd;  
  76.     MSG msg;  
  77.     WNDCLASS wndclass;  
  78.   
  79.     HWND handle = FindWindow(NULL, szWndName);  
  80.     if (handle != NULL)  
  81.     {  
  82.         MessageBox(NULL, TEXT("Application is already running"), szAppName, MB_ICONERROR);  
  83.         return 0;  
  84.     }  
  85.   
  86.     wndclass.style = CS_HREDRAW | CS_VREDRAW;  
  87.     wndclass.lpfnWndProc = WndProc;  
  88.     wndclass.cbClsExtra = 0;  
  89.     wndclass.cbWndExtra = 0;  
  90.     wndclass.hInstance = hInstance;  
  91.     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);  
  92.     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);  
  93.     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  94.     wndclass.lpszMenuName = NULL;  
  95.     wndclass.lpszClassName = szAppName;  
  96.   
  97.     if (!RegisterClass(&wndclass))  
  98.     {  
  99.         MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);  
  100.         return 0;  
  101.     }  
  102.   
  103.     // 此处使用WS_EX_TOOLWINDOW 属性来隐藏显示在任务栏上的窗口程序按钮  
  104.     hwnd = CreateWindowEx(WS_EX_TOOLWINDOW,  
  105.         szAppName, szWndName,  
  106.         WS_POPUP,  
  107.         CW_USEDEFAULT,  
  108.         CW_USEDEFAULT,  
  109.         CW_USEDEFAULT,  
  110.         CW_USEDEFAULT,  
  111.         NULL, NULL, hInstance, NULL);  
  112.   
  113.     ShowWindow(hwnd, iCmdShow);  
  114.     UpdateWindow(hwnd);  
  115.   
  116.     while (GetMessage(&msg, NULL, 0, 0))  
  117.     {  
  118.         TranslateMessage(&msg);  
  119.         DispatchMessage(&msg);  
  120.     }  
  121.     return msg.wParam;  
  122. }  
posted @ 2015-01-04 15:08  vcerror  阅读(1502)  评论(0编辑  收藏  举报