You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MFC开发类似日期组件的后台任务栏CPU使用率显示程序

MFC实现后台任务栏CPU监控程序

要实现后台运行、在任务栏通知区域(托盘)显示CPU使用率的MFC程序,核心分为系统托盘集成、CPU使用率获取、定期更新显示三个部分,具体步骤如下:

1. 创建后台MFC应用

新建MFC对话框应用,在OnInitDialog中隐藏主窗口,确保程序后台运行:

ShowWindow(SW_HIDE);
// 可选:修改窗口样式,避免主窗口在任务栏显示
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);

2. 集成系统托盘图标

系统托盘功能依赖Windows API的Shell_NotifyIcon,步骤如下:

2.1 定义托盘数据结构

在对话框类头文件中声明NOTIFYICONDATA变量和自定义消息:

#include <shellapi.h>
#pragma comment(lib, "shell32.lib")

#define WM_MY_NOTIFY WM_USER + 100

class CCPUMonitorDlg : public CDialogEx
{
    // ... 其他成员
private:
    NOTIFYICONDATA m_nid;
    afx_msg LRESULT OnNotifyIcon(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnDestroy();
    DECLARE_MESSAGE_MAP()
};

2.2 初始化托盘图标

在OnInitDialog中完成托盘图标初始化:

ZeroMemory(&m_nid, sizeof(m_nid));
m_nid.cbSize = sizeof(NOTIFYICONDATA);
m_nid.hWnd = m_hWnd;
m_nid.uID = IDI_MYAPP_ICON; // 替换为你的资源图标ID
m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
m_nid.uCallbackMessage = WM_MY_NOTIFY;
m_nid.hIcon = AfxGetApp()->LoadIcon(IDI_MYAPP_ICON);
_tcscpy_s(m_nid.szTip, _T("CPU使用率监控"));

// 添加托盘图标
Shell_NotifyIcon(NIM_ADD, &m_nid);

2.3 处理托盘事件

实现自定义消息响应函数,处理右键菜单(比如退出选项):

LRESULT CCPUMonitorDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
    if (wParam == IDI_MYAPP_ICON && lParam == WM_RBUTTONUP)
    {
        CMenu menu;
        menu.LoadMenu(IDR_MENU1); // 加载自定义右键菜单
        CMenu* pSubMenu = menu.GetSubMenu(0);
        POINT pt;
        GetCursorPos(&pt);
        pSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
    }
    return 0;
}

3. 获取系统CPU使用率

使用Windows性能计数器(PDH)获取CPU使用率,步骤如下:

3.1 初始化计数器

在类中声明PDH句柄,添加初始化函数:

#include <pdh.h>
#pragma comment(lib, "pdh.lib")

class CCPUMonitorDlg : public CDialogEx
{
    // ... 其他成员
private:
    PDH_HQUERY m_hQuery;
    PDH_HCOUNTER m_hCounter;
    BOOL InitCPUCounter();
    float GetCPUUsage();
};

实现初始化和获取函数:

BOOL CCPUMonitorDlg::InitCPUCounter()
{
    if (PdhOpenQuery(NULL, 0, &m_hQuery) != ERROR_SUCCESS)
        return FALSE;
    if (PdhAddCounter(m_hQuery, _T("\\Processor(_Total)\\% Processor Time"), 0, &m_hCounter) != ERROR_SUCCESS)
    {
        PdhCloseQuery(m_hQuery);
        return FALSE;
    }
    // 第一次采样,用于后续计算差值
    PdhCollectQueryData(m_hQuery);
    return TRUE;
}

float CCPUMonitorDlg::GetCPUUsage()
{
    PDH_FMT_COUNTERVALUE counterVal;
    // 第二次采样
    if (PdhCollectQueryData(m_hQuery) != ERROR_SUCCESS)
        return 0.0f;
    if (PdhGetFormattedCounterValue(m_hCounter, PDH_FMT_FLOAT, NULL, &counterVal) == ERROR_SUCCESS)
        return counterVal.fValue;
    return 0.0f;
}

在OnInitDialog中调用InitCPUCounter()完成初始化。

4. 定期更新托盘显示

使用MFC定时器定期获取CPU使用率并更新托盘:

4.1 设置定时器

在OnInitDialog中启动定时器(每秒更新一次):

SetTimer(1, 1000, NULL);

4.2 实现定时器回调

在OnTimer函数中更新托盘的提示文字或动态生成带文字的图标:

void CCPUMonitorDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == 1)
    {
        float cpuUsage = GetCPUUsage();
        CString strStatus;
        strStatus.Format(_T("CPU: %.1f%%"), cpuUsage);

        // 更新托盘提示文字
        m_nid.uFlags = NIF_TIP;
        _tcscpy_s(m_nid.szTip, strStatus);
        Shell_NotifyIcon(NIM_MODIFY, &m_nid);

        // 可选:动态生成带文字的托盘图标
        HICON hNewIcon = CreateIconWithText(strStatus);
        if (hNewIcon)
        {
            m_nid.uFlags = NIF_ICON;
            DestroyIcon(m_nid.hIcon); // 释放旧图标
            m_nid.hIcon = hNewIcon;
            Shell_NotifyIcon(NIM_MODIFY, &m_nid);
        }
    }
    CDialogEx::OnTimer(nIDEvent);
}

4.3 动态生成带文字的图标

实现CreateIconWithText函数,将CPU使用率绘制到图标上:

HICON CCPUMonitorDlg::CreateIconWithText(CString strText)
{
    HDC hDC = GetDC()->m_hDC;
    HDC hMemDC = CreateCompatibleDC(hDC);
    HBITMAP hBmp = CreateCompatibleBitmap(hDC, 16, 16); // 托盘图标标准尺寸
    HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp);

    // 填充背景
    RECT rect = {0, 0, 16, 16};
    FillRect(hMemDC, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

    // 设置字体和文字颜色
    SetTextColor(hMemDC, RGB(255, 255, 255));
    SetBkMode(hMemDC, TRANSPARENT);
    LOGFONT lf;
    ZeroMemory(&lf, sizeof(lf));
    lf.lfHeight = 12;
    lf.lfWeight = FW_BOLD;
    _tcscpy_s(lf.lfFaceName, _T("Arial"));
    HFONT hFont = CreateFontIndirect(&lf);
    HFONT hOldFont = (HFONT)SelectObject(hMemDC, hFont);

    // 居中绘制文字
    DrawText(hMemDC, strText, strText.GetLength(), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    // 创建图标
    ICONINFO ii;
    ii.fIcon = TRUE;
    ii.hbmColor = hBmp;
    ii.hbmMask = CreateBitmap(16, 16, 1, 1, NULL);
    HICON hIcon = CreateIconIndirect(&ii);

    // 清理资源
    SelectObject(hMemDC, hOldFont);
    DeleteObject(hFont);
    SelectObject(hMemDC, hOldBmp);
    DeleteObject(hBmp);
    DeleteDC(hMemDC);
    ReleaseDC(NULL);
    DeleteObject(ii.hbmMask);

    return hIcon;
}

5. 程序退出清理

在OnDestroy中移除托盘图标并释放资源:

void CCPUMonitorDlg::OnDestroy()
{
    Shell_NotifyIcon(NIM_DELETE, &m_nid);
    if (m_hQuery)
        PdhCloseQuery(m_hQuery);
    CDialogEx::OnDestroy();
}

内容的提问来源于stack exchange,提问作者Shellong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:51:28