使用Win32 API做个系统托盘图标

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

001 #include <windows.h>
002 #define IDR_PAUSE 12
003 #define IDR_START 13
004 /*
005 #include <shellapi.h>
006 #pragma   comment(lib,   "shell32.lib")
007 */
008 LPCTSTR szAppName = TEXT("服务程序");
009 LPCTSTR szWndName = TEXT("服务程序");
010 HMENU hmenu;//菜单句柄
011  
012 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAMlParam)
013 {
014     NOTIFYICONDATA nid;
015     UINT WM_TASKBARCREATED;
016     POINT pt;//用于接收鼠标坐标
017     int xx;//用于接收菜单选项返回值
018  
019     // 不要修改TaskbarCreated,这是系统任务栏自定义的消息
020     WM_TASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));
021     switch (message)
022     {
023     case WM_CREATE://窗口创建时候的消息.
024         nid.cbSize = sizeof(nid);
025         nid.hWnd = hwnd;
026         nid.uID = 0;
027         nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
028         nid.uCallbackMessage = WM_USER;
029         nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
030         lstrcpy(nid.szTip, szAppName);
031         Shell_NotifyIcon(NIM_ADD, &nid);
032         hmenu=CreatePopupMenu();//生成菜单
033         AppendMenu(hmenu,MF_STRING,IDR_PAUSE,"暂停服务");//为菜单添加两个选项
034         AppendMenu(hmenu,MF_STRING,IDR_START,"恢复服务");
035         break;
036     case WM_USER://连续使用该程序时候的消息.
037         if (lParam == WM_LBUTTONDOWN)
038             MessageBox(hwnd, TEXT("Win32 API 实现系统托盘程序,双击托盘可以退出!"), szAppName, MB_OK);
039         if (lParam == WM_LBUTTONDBLCLK)//双击托盘的消息,退出.
040             SendMessage(hwnd, WM_CLOSE, wParam, lParam);
041         if (lParam == WM_RBUTTONDOWN)
042         {
043             GetCursorPos(&pt);//取鼠标坐标
044             ::SetForegroundWindow(hwnd);//解决在菜单外单击左键菜单不消失的问题
045             EnableMenuItem(hmenu,IDR_PAUSE,MF_GRAYED);//让菜单中的某一项变灰
046             xx=TrackPopupMenu(hmenu,TPM_RETURNCMD,pt.x,pt.y,NULL,hwnd,NULL);//显示菜单并获取选项ID
047             if(xx==IDR_PAUSE) MessageBox(hwnd, TEXT("111"), szAppName, MB_OK);
048             if(xx==IDR_START) MessageBox(hwnd, TEXT("222"), szAppName, MB_OK);
049             if(xx==0) PostMessage(hwnd,WM_LBUTTONDOWN,NULL,NULL);
050             //MessageBox(hwnd, TEXT("右键"), szAppName, MB_OK);
051         }
052         break;
053     case WM_DESTROY://窗口销毁时候的消息.
054         Shell_NotifyIcon(NIM_DELETE, &nid);
055         PostQuitMessage(0);
056         break;
057     default:
058         /*
059         * 防止当Explorer.exe 崩溃以后,程序在系统系统托盘中的图标就消失
060         *
061         * 原理:Explorer.exe 重新载入后会重建系统任务栏。当系统任务栏建立的时候会向系统内所有
062         * 注册接收TaskbarCreated 消息的顶级窗口发送一条消息,我们只需要捕捉这个消息,并重建系
063         * 统托盘的图标即可。
064         */
065         if (message == WM_TASKBARCREATED)
066             SendMessage(hwnd, WM_CREATE, wParam, lParam);
067         break;
068     }
069     return DefWindowProc(hwnd, message, wParam, lParam);
070 }
071  
072 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
073                    LPSTR szCmdLine, int iCmdShow)
074 {
075     HWND hwnd;
076     MSG msg;
077     WNDCLASS wndclass;
078  
079     HWND handle = FindWindow(NULL, szWndName);
080     if (handle != NULL)
081     {
082         MessageBox(NULL, TEXT("Application is already running"), szAppName, MB_ICONERROR);
083         return 0;
084     }
085  
086     wndclass.style = CS_HREDRAW | CS_VREDRAW;
087     wndclass.lpfnWndProc = WndProc;
088     wndclass.cbClsExtra = 0;
089     wndclass.cbWndExtra = 0;
090     wndclass.hInstance = hInstance;
091     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
092     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
093     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
094     wndclass.lpszMenuName = NULL;
095     wndclass.lpszClassName = szAppName;
096  
097     if (!RegisterClass(&wndclass))
098     {
099         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 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Windows API中的Shell_NotifyIconGetRect函数来查询系统托盘中的图标数量。 具体步骤如下: 1. 枚举系统托盘中的所有图标,获取每个图标的位置信息。 2. 使用Shell_NotifyIconGetRect函数获取托盘区域的大小和位置。 3. 遍历每个图标的位置信息,如果该图标的位置在托盘区域内,则将计数器加一。 示例代码如下: ```c++ #include <windows.h> #include <shellapi.h> int GetTrayIconCount() { int count = 0; HWND trayWnd = FindWindow("Shell_TrayWnd", NULL); if (trayWnd == NULL) { return count; } HWND trayNotifyWnd = FindWindowEx(trayWnd, NULL, "TrayNotifyWnd", NULL); if (trayNotifyWnd == NULL) { return count; } RECT trayRect; Shell_NotifyIconGetRect(&GUID_NULL, &trayRect); HWND childWnd = FindWindowEx(trayNotifyWnd, NULL, "SysPager", NULL); if (childWnd != NULL) { childWnd = FindWindowEx(childWnd, NULL, "ToolbarWindow32", NULL); } else { childWnd = FindWindowEx(trayNotifyWnd, NULL, "ToolbarWindow32", NULL); } if (childWnd == NULL) { return count; } int buttonCount = SendMessage(childWnd, TB_BUTTONCOUNT, 0, 0); for (int i = 0; i < buttonCount; i++) { RECT buttonRect; SendMessage(childWnd, TB_GETITEMRECT, i, (LPARAM)&buttonRect); if (IntersectRect(&buttonRect, &buttonRect, &trayRect)) { count++; } } return count; } ``` 该函数首先获取系统托盘窗口的句柄,然后通过FindWindowEx函数获取托盘区域的句柄。接着使用Shell_NotifyIconGetRect函数获取托盘区域的大小和位置,并通过FindWindowEx函数获取托盘区域中的ToolbarWindow32控件。最后,遍历ToolbarWindow32控件中的所有按钮,并判断按钮的位置是否在托盘区域内,如果是,则将计数器加一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值