要获得及时的网速和流量信息,归根到底还是对经过网卡的数据量的处理。而经过网卡的数据可以根据方向分为两类,一类是进来的,另一类是出去的,确切地说就是上传和下载。
网速是单位时间内的数据量,本质其实还是流量。
上文提到的那个类MFNetTraffic中功能很完整,不经能获得流量信息,还转化为了网速,只要在程序中调用即可了。另外,由于那个类不是自己写的,也就没有做出任何修改,所以其中的某些函数对于本程序来所可能是从未调用的。
说了这么多,其实监控网速和流量最关键的问题已经解决了,那就是如何获取当前的网速即流量信息,接下去的目标只是将它们合理显示出来。
现在流行的做法是,做一个小的矩形悬浮窗口,动态显示网速即流量信息,类似360和金山的那种。而这种方法也确实很经典,所以本程序也采用这种显示方式。
小窗口即是一个无标题栏的对话框,在对话框属性中取消勾选标题栏就行了。另外,显示信息就采用Text控件。
具体的流程是:启动程序->弹出小窗口->获取信息->显示信息。
因为要动态的显示信息,所以设置一个计时器函数,每隔一段时间获取一次信息并显示到小窗口上。
另外,一些追加的细节:
1、小窗口是始终置顶的,这里就没有添加取消置顶的功能,一来是因为小窗口很小,二来我为其添加了调整透明度的功能,如果实在不想看到小窗口,将其透明度设为最小值即可。
2、透明度的设置函数:
参数就一个byte,取值0-255,即为透明度的范围,0为完全透明,255为不透明。(因为实在vc6.0上,所以比较复杂,高版本上直接调用SetLayeredWindowAttributes函数即可)
/************************************************************************/
/* 设置窗体透明 */
/************************************************************************/
BOOL CTraffic_MonitoringDlg::SetWindowTransparency(int Byte)
{
// 设置窗体透明
COLORREF maskColor = GetSysColor(COLOR_3DFACE); // 获取窗体颜色
SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(GetSafeHwnd(),GWL_EXSTYLE)|0x00080000);
HINSTANCE hInst = LoadLibrary(_T("User32.dll"));
if (hInst)
{
typedef BOOL (WINAPI *MyFun)(HWND,COLORREF,BYTE,DWORD);
MyFun myfun = NULL;
myfun = (MyFun)GetProcAddress(hInst, "SetLayeredWindowAttributes");
if (myfun)
{
myfun(GetSafeHwnd(),maskColor,Byte,2); // 100是透明度(范围0-255)
}
else
{
FreeLibrary(hInst);
return FALSE;
}
FreeLibrary(hInst);
}
return TRUE;
}
// 隐藏任务栏图标
ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW,0);
所以同时显示太占空间,所以决定默认只显示两项,即上传和下载的网速。其他信息则影藏起来,若用户需要查看,鼠标左键双击小窗口,会弹出一个扩展窗口,显示剩下的四项信息。
窗口扩展与收缩功能的实现函数:
/************************************************************************/
/* 展开、收缩对话框 */
/************************************************************************/
void CTraffic_MonitoringDlg::ExtendDlg(int nResourceID, BOOL bExpand)
{
// nResourceID为分割控件的ID(此处为picture控件)
// 如果bExpand==TRUE,则扩展对话框为最大;
// 否则缩小对话框,新的对话框的底部为资源nResourceID控件分割
static CRect rcLarge;
static CRect rcSmall;
// 在开始时,保存对话框的最大和最小尺寸
if(rcLarge.IsRectNull())
{
CRect rcLandmark;
// 得到分割条的指针
CWnd* pWndLandmark=GetDlgItem(nResourceID);
ASSERT(pWndLandmark);
// 得到对话框的尺寸
GetWindowRect(rcLarge);
// 得到分割条在对话框中的位置
pWndLandmark->GetWindowRect(rcLandmark);
rcSmall=rcLarge;
rcSmall.bottom=rcLandmark.top;
}
if(bExpand)
{
// 扩展对话框:重新设置对话框到其原始(最大)尺寸(rcLarge)
SetWindowPos(NULL,0,0,rcLarge.Width(),rcLarge.Height(),
SWP_NOMOVE|SWP_NOZORDER);
}
else
{
// 缩小对话框:重新设置对话框到其最小尺寸(rcSmall)
SetWindowPos(NULL,0,0,rcSmall.Width(),rcSmall.Height(),
SWP_NOMOVE|SWP_NOZORDER);
}
}
具体如何实现托盘:http://blog.csdn.net/wwkaven/article/details/30487699
6、为了程序尽可能简单,添加一个删除托盘图标的功能,这样要退出程序通过右击小窗口实现。
7、最后一点,资源管理器重启后,托盘图标丢失的问题:
http://blog.csdn.net/wwkaven/article/details/32108845
程序:http://download.csdn.net/detail/wwkaven/7515523
完整源代码:http://download.csdn.net/detail/wwkaven/7515507