Win32 API 实现系统托盘程序

jopen 10年前

托盘程序就是运行在系统托盘区域的程序,显示为桌面右下角显示区域的一个小图标。通常托盘程序带有几种功能:托盘菜单,托盘图标,气泡提示,托盘提示。例如QQ收到消息后,会在系统右下角显示闪动QQ图标。

主程序Tray.cpp

    #include <windows.h>        #include "resource.h"                #define WM_TRAY (WM_USER + 100)        #define WM_TASKBAR_CREATED RegisterWindowMessage(TEXT("TaskbarCreated"))                #define APP_NAME    TEXT("托盘程序")        #define APP_TIP     TEXT("Win32 API 实现系统托盘程序")                NOTIFYICONDATA nid;     //托盘属性        HMENU hMenu;            //托盘菜单                //实例化托盘        void InitTray(HINSTANCE hInstance, HWND hWnd)        {            nid.cbSize = sizeof(NOTIFYICONDATA);            nid.hWnd = hWnd;            nid.uID = IDI_TRAY;            nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;            nid.uCallbackMessage = WM_TRAY;            nid.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TRAY));            lstrcpy(nid.szTip, APP_NAME);                    hMenu = CreatePopupMenu();//生成托盘菜单            //为托盘菜单添加两个选项            AppendMenu(hMenu, MF_STRING, ID_SHOW, TEXT("提示"));            AppendMenu(hMenu, MF_STRING, ID_EXIT, TEXT("退出"));                    Shell_NotifyIcon(NIM_ADD, &nid);        }                //演示托盘气泡提醒        void ShowTrayMsg()        {            lstrcpy(nid.szInfoTitle, APP_NAME);            lstrcpy(nid.szInfo, TEXT("收到一条消息!"));            nid.uTimeout = 1000;            Shell_NotifyIcon(NIM_MODIFY, &nid);        }                LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)        {            switch (uMsg)            {            case WM_TRAY:                switch(lParam)                {                case WM_RBUTTONDOWN:                    {                        //获取鼠标坐标                        POINT pt; GetCursorPos(&pt);                                //解决在菜单外单击左键菜单不消失的问题                        SetForegroundWindow(hWnd);                                //使菜单某项变灰                        //EnableMenuItem(hMenu, ID_SHOW, MF_GRAYED);                                    //显示并获取选中的菜单                        int cmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, NULL, hWnd,                             NULL);                        if(cmd == ID_SHOW)                            MessageBox(hWnd, APP_TIP, APP_NAME, MB_OK);                        if(cmd == ID_EXIT)                             PostMessage(hWnd, WM_DESTROY, NULL, NULL);                    }                    break;                case WM_LBUTTONDOWN:                    MessageBox(hWnd, APP_TIP, APP_NAME, MB_OK);                    break;                case WM_LBUTTONDBLCLK:                    break;                }                break;            case WM_DESTROY:                //窗口销毁时删除托盘                Shell_NotifyIcon(NIM_DELETE, &nid);                PostQuitMessage(0);                break;            case WM_TIMER:                ShowTrayMsg();                KillTimer(hWnd, wParam);                break;            }            if (uMsg == WM_TASKBAR_CREATED)            {                //系统Explorer崩溃重启时,重新加载托盘                Shell_NotifyIcon(NIM_ADD, &nid);            }            return DefWindowProc(hWnd, uMsg, wParam, lParam);        }                int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,             LPSTR /*lpCmdLine*/, int iCmdShow)        {            HWND hWnd;            MSG msg;            WNDCLASS wc = { 0 };            wc.style = NULL;            wc.hIcon = NULL;            wc.cbClsExtra = 0;            wc.cbWndExtra = 0;            wc.hInstance = hInstance;            wc.lpfnWndProc = WndProc;            wc.hbrBackground = NULL;            wc.lpszMenuName = NULL;            wc.lpszClassName = APP_NAME;            wc.hCursor = NULL;                    if (!RegisterClass(&wc)) return 0;                    hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, APP_NAME, APP_NAME, WS_POPUP, CW_USEDEFAULT,                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);                    ShowWindow(hWnd, iCmdShow);            UpdateWindow(hWnd);                    InitTray(hInstance, hWnd);          //实例化托盘            SetTimer(hWnd, 3, 1000, NULL);      //定时发消息,演示气泡提示功能                    while (GetMessage(&msg, NULL, 0, 0))            {                TranslateMessage(&msg);                DispatchMessage(&msg);            }            return msg.wParam;        }  

资源头文件 resource.h
    #define IDI_TRAY    101        #define ID_SHOW     40001        #define ID_EXIT     40002  

资源文件 resource.rc
 
    #include "resource.h"                IDI_TRAY ICON DISCARDABLE "ico.ico"  
</div> </div>
编译很简单,使用 Visual Studio建立一个空项目,建好以上3个文件,再找一个ico图标,保存为ico.ico,即可编译。