1. TrafficMonitor 项目概述
TrafficMonitor 是一款基于 MFC 框架开发的 Windows 桌面监控工具,它通过系统级 API 调用实现了对计算机各项性能指标的实时监测。作为一名长期从事 Windows 桌面应用开发的工程师,我认为这款工具的设计充分体现了 Windows 平台下高性能监控类应用的典型架构特点。
1.1 核心功能解析
该工具的核心监控能力可以分为三大类:
网络监控模块:
- 实时显示每个网络适配器的下载/上传速度(精确到字节/秒)
- 支持历史流量统计和日历视图
- 独特的"今日流量"累计功能,帮助用户掌握每日网络使用情况
系统资源监控:
- CPU 使用率监控支持多种检测方式(PDH API、GetSystemTimes等)
- 内存使用情况显示包括使用量和百分比两种形式
- 创新性地在任务栏区域显示精简监控信息
硬件状态监控(完整版特有):
- 通过封装 LibreHardwareMonitor 实现温度监控
- 支持 CPU/GPU/硬盘温度监测
- 提供 GPU 使用率监控功能
1.2 技术架构亮点
从技术实现角度看,这个项目有几个值得关注的架构决策:
混合渲染架构:
- 同时支持 GDI 和 Direct2D 两种渲染后端
- 针对不同 Windows 版本自动选择最佳渲染策略
- 创新的 DirectComposition 集成方案
插件系统设计:
- 基于 DLL 的插件扩展机制
- 定义清晰的插件接口规范(API Version 7)
- 支持自定义绘制项和标准文本项两种插件类型
多窗口协同:
- 主浮动窗口提供完整监控信息
- 任务栏窗口实现精简信息展示
- 两窗口共享同一数据源但独立渲染
2. 整体架构设计
2.1 分层架构解析
TrafficMonitor 采用了经典的分层架构设计,各层职责分明:
表示层(Presentation Layer)
cpp复制class CTrafficMonitorDlg : public CDialogEx {
// 主浮动窗口实现
virtual BOOL OnInitDialog();
virtual void OnPaint();
// ...
};
class CTaskBarDlg : public CDialogEx {
// 任务栏窗口基类
virtual void AdjustTaskbarWndPos() = 0;
// ...
};
- 使用 MFC 的 CDialogEx 作为基础窗口类
- 针对不同 Windows 版本实现差异化任务栏窗口
- 所有 UI 元素支持 DPI 感知和高分屏适配
业务逻辑层(Business Logic Layer)
cpp复制class CCPUUsage {
public:
enum Method { CPU_TIME, PDH, HARDWARE_MONITOR };
int GetCpuUsage(); // 根据配置选择检测方法
};
- 网络监控基于 IP Helper API 实现
- CPU 监控提供多种实现方式以适应不同系统环境
- 硬件监控通过 C++/CLI 包装 .NET 组件实现
数据持久层(Persistence Layer)
cpp复制class CSettingsHelper {
public:
bool Load(const wstring& file);
bool Save();
// INI 文件读写接口
};
- 配置存储使用传统的 INI 格式
- 历史流量数据采用二进制格式存储
- 皮肤系统支持 XML 和 INI 两种定义方式
2.2 关键类关系
核心类之间的协作关系值得深入分析:
应用单例模式:
cpp复制// 全局应用实例
class CTrafficMonitorApp : public CWinApp {
static CTrafficMonitorApp theApp; // 唯一实例
// 共享状态数据
};
窗口继承体系:
code复制CDialog (MFC)
└─ CBaseDialog (模板方法基类)
├─ CTabDlg (选项卡对话框基类)
└─ CTaskBarDlg (策略模式基类)
├─ CClassicalTaskbarDlg
└─ CWin11TaskbarDlg
这种设计实现了:
- 公共行为通过基类统一处理(如DPI适配)
- 版本特定逻辑通过子类差异化实现
- 模板方法模式控制窗口生命周期
3. 设计模式应用
3.1 单例模式的实际应用
项目中单例模式的使用颇具特色:
应用主单例:
cpp复制// 传统MFC方式声明应用实例
CTrafficMonitorApp theApp;
// 全局状态访问示例:
double speed = theApp.m_in_speed;
Meyer's 单例实现:
cpp复制// 皮肤管理器实现
class CSkinManager {
public:
static CSkinManager& Instance() {
static CSkinManager instance; // 局部静态变量
return instance;
}
};
这种实现方式保证了:
- 线程安全的初始化(C++11起保证)
- 延迟加载(首次访问时构造)
- 自动销毁(程序退出时)
3.2 工厂模式创新实现
渲染后端的工厂模式实现值得学习:
渲染类型定义:
cpp复制enum class RenderType {
DEFAULT, // GDI
D2D1, // Direct2D
D2D1_WITH_DCOMPOSITION // Direct2D + DirectComposition
};
工厂方法核心:
cpp复制std::tuple<IDrawBuffer*, IDrawCommon*>
CreateRenderObjects(RenderType type) {
switch(type) {
case RenderType::D2D1:
return {new D2DDrawBuffer(), new D2DDrawCommon()};
// ...其他类型处理
}
}
这个工厂的特殊之处在于:
- 使用 std::tuple 返回多个关联对象
- 采用栈分配策略避免堆碎片
- 内置类型安全检查机制
3.3 策略模式实战
任务栏窗口的策略模式应用展示了良好的扩展性:
策略接口:
cpp复制class CTaskBarDlg : public CDialogEx {
public:
virtual void InitTaskbarWnd() = 0;
virtual void AdjustTaskbarWndPos() = 0;
};
具体策略:
cpp复制class CWin11TaskbarDlg : public CTaskBarDlg {
void InitTaskbarWnd() override {
// Win11特有的任务栏集成方式
}
};
策略选择的运行时逻辑:
cpp复制CTaskBarDlg* CreateTaskbarDlg() {
if (IsWindows11OrGreater())
return new CWin11TaskbarDlg();
else
return new CClassicalTaskbarDlg();
}
4. 关键技术实现细节
4.1 渲染子系统架构
渲染抽象层设计
cpp复制class IDrawCommon {
public:
virtual void DrawWindowText(CRect rect, LPCTSTR text,
COLORREF color) = 0;
virtual void DrawBitmap(HBITMAP hbitmap, CPoint point) = 0;
// ...其他绘图接口
};
GDI 实现要点:
cpp复制class CDrawCommon : public IDrawCommon {
CDC* m_pDC; // 设备上下文
void DrawWindowText(...) override {
m_pDC->DrawText(text, rect, DT_LEFT);
}
};
Direct2D 实现特点:
cpp复制class CD2DDrawCommon : public IDrawCommon {
ComPtr<ID2D1DeviceContext> m_pDeviceContext;
void DrawWindowText(...) override {
// 使用DirectWrite进行文本渲染
m_pDeviceContext->DrawTextLayout(...);
}
};
DPI 感知实现
cpp复制int DPIScale(int value) const {
return MulDiv(value, m_dpi, 96);
}
void OnDpiChanged(int newDpi) {
m_dpi = newDpi;
// 重建所有DPI相关资源
RecreateFonts();
RecreateBitmaps();
}
4.2 插件系统设计
插件接口规范
cpp复制class IPluginItem {
public:
virtual const wchar_t* GetItemName() = 0;
virtual const wchar_t* GetItemValueText() = 0;
virtual bool IsCustomDraw() = 0;
};
插件加载流程
- 扫描 plugins 目录下的 DLL 文件
- 动态加载 DLL 并查找入口函数
- 验证插件版本兼容性
- 初始化插件实例
- 注册插件显示项
插件与宿主通信
cpp复制class ITrafficMonitor {
public:
virtual double GetMonitorValue(MonitorValueType) = 0;
virtual void ShowNotifyMessage(const wchar_t*) = 0;
};
4.3 性能优化技巧
位图缓存策略:
cpp复制class CBitmapCache {
std::unordered_map<HBITMAP, CacheEntry> m_cache;
void CleanupExpired() {
// 定期清理过期缓存
}
};
设备资源管理:
cpp复制class CD2DResource {
static std::vector<CD2DResource*> s_allResources;
public:
CD2DResource() { s_allResources.push_back(this); }
virtual void Recreate() = 0;
static void RecreateAll() {
for(auto res : s_allResources) res->Recreate();
}
};
5. 开发经验与最佳实践
5.1 Windows 桌面开发心得
消息处理技巧:
cpp复制BEGIN_MESSAGE_MAP(CTrafficMonitorDlg, CDialog)
ON_WM_TIMER()
ON_MESSAGE(WM_MONITOR_INFO_UPDATED, OnInfoUpdated)
END_MESSAGE_MAP()
DPI 适配经验:
- 所有尺寸计算考虑 DPI 缩放因子
- 使用系统DPI感知API
- 高DPI图标资源准备
5.2 性能监控注意事项
精确计时实现:
cpp复制LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
// 执行监控代码
QueryPerformanceCounter(&end);
double elapsed = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
低开销数据采集:
- 合理设置采样间隔(默认1秒)
- 避免在UI线程执行耗时操作
- 使用轻量级同步机制
5.3 兼容性处理方案
Windows 版本检测:
cpp复制bool IsWindows11OrGreater() {
OSVERSIONINFOEXW osvi = { sizeof(osvi) };
osvi.dwBuildNumber = 22000; // Win11起始build号
DWORDLONG mask = VerSetConditionMask(0, VER_BUILDNUMBER, VER_GREATER_EQUAL);
return VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, mask);
}
异常处理策略:
cpp复制try {
// 调用可能失败的API
} catch(const ComException& e) {
// 处理COM异常
LogError(L"COM error: %s", e.what());
RecreateResources();
}
6. 扩展与定制开发
6.1 皮肤系统开发指南
皮肤文件结构:
code复制skin.ini
[Main]
Background=bg.png
TextColor=RGB(255,255,255)
[CPU]
Position=10,20
Font=Segoe UI,12
皮肤加载流程:
- 解析皮肤配置文件
- 加载背景图片资源
- 创建指定字体和颜色
- 计算各元素布局位置
6.2 插件开发实战
简单插件示例:
cpp复制class CTimePlugin : public ITMPlugin {
public:
IPluginItem* GetItem(int index) override {
return &m_timeItem; // 返回时间显示项
}
private:
CTimeItem m_timeItem;
};
extern "C" __declspec(dllexport) ITMPlugin* TMPluginGetInstance() {
static CTimePlugin instance;
return &instance;
}
插件配置管理:
cpp复制// 插件配置存储路径
wstring configPath = theApp->GetPluginConfigDir() + L"\\myplugin.ini";
6.3 监控项扩展方法
添加新监控项步骤:
- 在业务层实现数据采集逻辑
- 更新全局状态结构体
- 在UI层添加显示处理
- 考虑是否需要历史记录
自定义绘制实现:
cpp复制void CMyItem::DrawItem(HDC hdc, int x, int y, int w, int h) {
// 自定义绘制逻辑
Graphics graphics(hdc);
Pen pen(Color(255, 0, 0), 2);
graphics.DrawLine(&pen, x, y, x + w, y + h);
}
7. 项目演进建议
7.1 架构改进方向
现代C++特性应用:
- 使用 std::unique_ptr 管理资源
- 采用 std::atomic 替代临界区
- 使用 std::chrono 进行时间处理
模块化重构:
- 将硬件监控拆分为独立模块
- 使用接口隔离渲染子系统
- 引入依赖注入框架
7.2 功能扩展思路
网络监控增强:
- 按进程统计流量
- 流量限额提醒
- 网络连接监控
系统监控扩展:
- 磁盘IO监控
- 电池状态监测
- 网络延迟测试
7.3 跨平台可能性
兼容层设计:
cpp复制class IPlatformAdapter {
public:
virtual double GetCpuUsage() = 0;
virtual NetworkStats GetNetworkStats() = 0;
};
// Windows实现
class WindowsAdapter : public IPlatformAdapter {
// 使用Windows API实现
};
跨平台构建系统:
- 使用 CMake 替代 MSBuild
- 抽象平台相关代码
- 条件编译处理差异
这个项目展示了如何基于传统MFC框架构建现代化的系统监控工具。通过分析其架构设计和技术实现,我们可以学习到许多Windows平台开发的实用技巧和最佳实践。对于需要进行类似工具开发的工程师来说,其中的设计模式和架构思想尤其值得借鉴。