VS2013/MFC 自绘控件获取系统CPU和物理内存使用率

一、CHistogramCtrl类介绍

这是CodeProject网站的一个优秀的类,能够在静态文本控件上实现曲线图的绘制,源代码网址如下:CHistogramCtrl, a windows 2000 like histogram control。源代码放到VS2013环境中只需要做一点修改就可以使用。这个类的具体代码如下:

HistogramCtrl.h

#if !defined(AFX_HISTOGRAMCTRL_H_H)
#define AFX_HISTOGRAMCTRL_H_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000  定义编译器版本
// HistogramCtrl.h : header file
//

#include "AfxTempl.h"
/
// CHistogramCtrl window

class CHistogramCtrl : public CWnd
{
// Construction
public:
	CHistogramCtrl();

// Attributes
public:
	typedef enum SPEED{ LOW_SPEED = 3000, NORMAL_SPEED = 1000, HIGH_SPEED = 500, IDLE = 0 };

// Operations
public:
	BOOL Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT uID);
	void SetRange(UINT uLower, UINT uUpper);

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CHistogramCtrl)
	//}}AFX_VIRTUAL

// Implementation
public:
	BOOL SetGridsColor(COLORREF cr);
	BOOL SetBkColor(COLORREF cr);
	void SetPen(int nWidth, COLORREF crColor);
	CHistogramCtrl::SPEED SetSpeed(CHistogramCtrl::SPEED uSpeed);
	void SetPos(UINT uPos);
	virtual ~CHistogramCtrl();

	// Generated message map functions
protected:
	//{{AFX_MSG(CHistogramCtrl)
	afx_msg void OnPaint();
	afx_msg void OnTimer(UINT nIDEvent);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
private:
	enum SPEED m_uSpeed;
	UINT m_yPos;
	UINT m_yPreviousPos;
	UINT m_uOffset;

	void DrawLine();
	BOOL InvalidateCtrl();
	UINT GetAverage();

	CDC *m_pMemDC;

	UINT m_uLower;
	UINT m_uUpper;

	CRect m_rcClient;
	CPen m_colorPen;

	int m_nFirstLinePos;

	COLORREF m_crBackGround;
	COLORREF m_crGrids;

	CList<UINT, UINT&> *m_pList;
};

/

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_HISTOGRAMCTRL_H_H)

HistogramCtrl.cpp

/*
Author:
	Mehdi Mousavi

Email:
	mehdi_mousavi@hotmail.com
	webmaster@modemmania.com

Date of release:
	14th of April 2001

Description:
	The initial idea of doing this code has been put into my mind when my love asked me
	to go to a clinic in order to check out my heart. You know, doctors have got some
	sort of plotters that plots the information obtained from the heart on a piece of
	paper as a histogram. The idea has been dropped into my mind there!

Dedicated to:
	My love, Cindy

Copyright & disclaimer:
	Permission is granted to distribute *unmodified* version of this source code.
	You are entitled to use CHistogramCtrl for both commercial and/or educational
	purposes as far as you keep these comments intact. Please feel free to post
	any additions to the author.
*/

#include "stdafx.h"
#include "MyTaskManager.h"
#include "HistogramCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CHistogramCtrl

CHistogramCtrl::CHistogramCtrl()
{
	m_nFirstLinePos = 13;

	m_pMemDC = NULL;
	m_pList = NULL;
	m_uSpeed = IDLE;

	m_crBackGround = RGB(0, 0, 0);
	m_crGrids = RGB(0, 130, 66);

	SetPen(1, RGB(0, 255, 0));
	SetRange(1, 100);
}

CHistogramCtrl::~CHistogramCtrl()
{
	if(m_pMemDC)
		delete m_pMemDC;

	if(m_pList)
		delete m_pList;
}


BEGIN_MESSAGE_MAP(CHistogramCtrl, CWnd)
	//{{AFX_MSG_MAP(CHistogramCtrl)
	ON_WM_PAINT()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/
// CHistogramCtrl message handlers


BOOL CHistogramCtrl::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT uID)
{
	//Postcondition:
	//	Creates a window within the "rect" region of the client screen
	//	Returns TRUE if the function creates the control successfully
	//	or FALSE if it fails.

	BOOL bRet = CWnd::CreateEx(WS_EX_CLIENTEDGE, 
								AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW),
								NULL,
								dwStyle,
								rect.left,
								rect.top,
								rect.right - rect.left,
								rect.bottom - rect.top,
								pParentWnd->GetSafeHwnd(),
								(HMENU)uID);

	if(!bRet)
		return FALSE;

	m_pMemDC = new CDC;
	if(!m_pMemDC)
		return FALSE;

	m_pList = new CList<UINT, UINT&>;
	if(!m_pList)
		return FALSE;

	GetClientRect(m_rcClient);

	if(!InvalidateCtrl())
		return FALSE;

	SetSpeed(CHistogramCtrl::NORMAL_SPEED);
	
	return TRUE;
}

void CHistogramCtrl::SetRange(UINT uLower, UINT uUpper)
{
	ASSERT(uLower && uUpper && uLower < uUpper);
	//Postcondition:
	//	Sets the upper and lower (limits) range
	m_uUpper = uUpper - uLower + 1;
	m_uLower = 1;
	m_uOffset = uLower - 1;
}

BOOL CHistogramCtrl::InvalidateCtrl()
{
	//Postcondition:初始化网格
	//	Paints the entire client area of the control
	//	Returns TRUE if it's done successfuly or FALSE if it fails

	CClientDC dc(this);

	if(m_pMemDC->GetSafeHdc())
		return FALSE;

	if(!m_pMemDC->CreateCompatibleDC(&dc))
		return FALSE;

	CBitmap bmp;
	if(!bmp.CreateCompatibleBitmap(&dc, m_rcClient.Width(), m_rcClient.Height()))
		return FALSE;

	if(!m_pMemDC->SelectObject(bmp))
		return FALSE;

	//Set the background color of the control
	CBrush bkBrush;
	if(!bkBrush.CreateSolidBrush(m_crBackGround))
		return FALSE;
	
	m_pMemDC->FillRect(m_rcClient, &bkBrush);

	//Select a specified pen to the device context to draw background lines
	CPen bkLinesPen;
	if(!bkLinesPen.CreatePen(PS_SOLID, 1, m_crGrids))
		return FALSE;

	if(!m_pMemDC->SelectObject(bkLinesPen))
		return FALSE;

	//Draw background lines
	for(register int i = m_rcClient.left - 1; i < m_rcClient.right; i += 13)
	{//画竖直线
		m_pMemDC->MoveTo(i, m_rcClient.top);
		m_pMemDC->LineTo(i, m_rcClient.bottom);
	}

	for(register int j = m_rcClient.top - 1; j < m_rcClient.bottom; j += 13)
	{//画水平线
		m_pMemDC->MoveTo(m_rcClient.left, j);
		m_pMemDC->LineTo(m_rcClient.right, j);
	}

	m_yPreviousPos = m_yPos = m_rcClient.bottom + 1;

	InvalidateRect(m_rcClient);

	return TRUE;
}

void CHistogramCtrl::OnPaint() 
{
	CPaintDC dc(this);

	if(m_pMemDC->GetSafeHdc())
		dc.BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), m_pMemDC, 0, 0, SRCCOPY);
}

void CHistogramCtrl::DrawLine()
{
	//Postcondition:
	//	Draws the histogram within the client area of the control

	if(!m_pMemDC->GetSafeHdc())
		return;

	//定时器刷新需要重绘的矩形区域,每次左移3个像素
	CRect bkRect(m_rcClient.right - 3, m_rcClient.top, m_rcClient.right, m_rcClient.bottom);

	CBrush bkBrush;
	bkBrush.CreateSolidBrush(m_crBackGround);
	m_pMemDC->FillRect(bkRect, &bkBrush);

	//获取内存中DC,并将其向左错位复制到显示DC,错位3个像素
	m_pMemDC->BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), m_pMemDC, 3, 0, SRCCOPY);

	CPen myPen;
	myPen.CreatePen(PS_SOLID, 1, m_crGrids);
	m_pMemDC->SelectObject(myPen);

	//画右边空出来的网格,计算左边第一条竖线位置
	m_nFirstLinePos -= 3;
	if(m_nFirstLinePos < 0)
		m_nFirstLinePos += 13;

	//计算右边要画的竖线位置
	int nX = m_rcClient.right - ((m_rcClient.right - m_nFirstLinePos) % 13) - 1;
	m_pMemDC->MoveTo(nX, m_rcClient.top);
	m_pMemDC->LineTo(nX, m_rcClient.bottom);


	for(register int j = m_rcClient.top - 1; j < m_rcClient.bottom; j += 13)
	{
		m_pMemDC->MoveTo(bkRect.left - 3, j);
		m_pMemDC->LineTo(bkRect.right, j);
	}

	UINT uAverage = GetAverage();
	TRACE("uAverage: %u\r\n", uAverage);
	if(uAverage)
		m_yPos = m_rcClient.bottom - (m_rcClient.bottom * uAverage/ m_uUpper);

	if(m_yPreviousPos == (unsigned)m_rcClient.bottom + 1)
		m_yPreviousPos = m_yPos;
	
	m_pMemDC->SelectObject(m_colorPen);
	m_pMemDC->MoveTo(m_rcClient.right - 11 - 3, m_yPreviousPos);
	m_pMemDC->LineTo(m_rcClient.right - 11, m_yPos);
	
	m_yPreviousPos = m_yPos;

	Invalidate();
}

void CHistogramCtrl::SetPos(UINT uPos)
{
	uPos -= m_uOffset;
	ASSERT(uPos <= m_uUpper && uPos >= m_uLower);

	//Postcondition:
	//	Adds the specified point to a list, so that we
	//	would be able to draw the histogram within the
	//	specified intervals.
	m_pList->AddHead(uPos);
}

void CHistogramCtrl::OnTimer(UINT nIDEvent) 
{
	DrawLine();
}

CHistogramCtrl::SPEED CHistogramCtrl::SetSpeed(enum SPEED uSpeed)
{
	enum SPEED oldSpeed = m_uSpeed;
	m_uSpeed = uSpeed;

	KillTimer(0);

	if(uSpeed != CHistogramCtrl::IDLE)
		SetTimer(0, m_uSpeed, NULL);

	return oldSpeed;
}

void CHistogramCtrl::SetPen(int nWidth, COLORREF crColor)
{
	m_colorPen.DeleteObject();
	m_colorPen.CreatePen(PS_SOLID, nWidth, crColor);
}

BOOL CHistogramCtrl::SetBkColor(COLORREF cr)
{
	BOOL bRet = FALSE;
	enum SPEED oldSpeed = SetSpeed(CHistogramCtrl::IDLE);

	m_crBackGround = cr;

	CClientDC dc(this);

	int oldPos = m_nFirstLinePos;
	m_nFirstLinePos = 13;
	if(m_pMemDC->DeleteDC())
		if(InvalidateCtrl())
			bRet = TRUE;

	if(!bRet)
		m_nFirstLinePos = oldPos;

	SetSpeed(oldSpeed);

	return bRet;
}

BOOL CHistogramCtrl::SetGridsColor(COLORREF cr)
{
	BOOL bRet = FALSE;
	enum SPEED oldSpeed = SetSpeed(CHistogramCtrl::IDLE);

	m_crGrids = cr;

	CClientDC dc(this);

	int oldPos = m_nFirstLinePos;
	m_nFirstLinePos = 13;
	if(m_pMemDC->DeleteDC())
		if(InvalidateCtrl())
			bRet = TRUE;

	if(!bRet)
		m_nFirstLinePos = oldPos;

	SetSpeed(oldSpeed);

	return bRet;
}

UINT CHistogramCtrl::GetAverage()
{
	UINT uCounter = 0, uSum = 0;
	while(!m_pList->IsEmpty())
	{
		uSum += m_pList->RemoveTail();
		uCounter++;
	}

	return uCounter ? uSum / uCounter : 0;
}

 做出来的控件如下:

 二、获取系统CPU使用率和物理内存使用率

1. 新建一个MFC应用程序,项目名称为MyTaskMan,保留确定按钮,如下图所示

2. 添加四个静态文本,设置用于显示曲线的两个静态文本控件Border为TRUE,设置用于显示CPU的控件ID为IDC_CPUCurve,用于显示物理内存的控件ID为IDC_MemoryCurve,如下图所示

3. 添加CHistogramCtrl类

在解决方案资源管理器选项卡中,项目名称右键添加现有项,将HistogramCtrl.cpp和HistogramCtrl.h,添加到项目中。修改HistogramCtrl.cpp中的头文件

在对话框类中添加两个CHistogramCtrl类对象,然后在MyTaskManDlg.h : 头文件中添加文件头#include "HistogramCtrl.h"

在CMyTaskManDlg类初始化函数OnInitDialog()中添加如下代码,同样要添加文件头#include "HistogramCtrl.h",在静态文本控件中显示绘图控件:

    CRect rect;
	GetDlgItem(IDC_CPUCurve)->GetWindowRect(rect);
	ScreenToClient(rect);
	m_ShowCPU.Create(WS_VISIBLE | WS_CHILD | WS_TABSTOP, rect, this, 1000);
	m_ShowCPU.SetRange(1, 100);
	m_ShowCPU.SetSpeed(CHistogramCtrl::HIGH_SPEED);
	//m_ShowCPU.SetGridsColor(RGB(0, 0, 0));
	//m_ShowCPU.SetBkColor(RGB(255, 255, 255));
	//m_ShowCPU.SetPen(1, RGB(0, 255, 0));

	CRect rect2;
	GetDlgItem(IDC_MemoryCurve)->GetWindowRect(rect2);
	ScreenToClient(rect2);
	m_ShowMemory.Create(WS_VISIBLE | WS_CHILD | WS_TABSTOP, rect2, this, 1000);
	m_ShowMemory.SetRange(1, 100);
	m_ShowMemory.SetSpeed(CHistogramCtrl::HIGH_SPEED);
	//m_ShowMemory.SetGridsColor(RGB(0, 0, 0));
	//m_ShowMemory.SetBkColor(RGB(255, 255, 255));
	m_ShowMemory.SetPen(2, RGB(255, 0, 0));

 运行结果如下:

 4. 添加自定义函数获取系统CPU使用率和物理内存使用率

获取CPU使用率函数:

void CMyTaskManDlg::GetCpuState(int& nStr)
{
	static LONGLONG nFree{}, nNt{}, nUser{};
	static LONGLONG nFreet{}, nNtt{}, nUsert{};
	static DOUBLE nHave{};
	GetSystemTimes((PFILETIME)&nFree, (PFILETIME)&nNt, (PFILETIME)&nUser);
	nHave = (DOUBLE)(nFree - nFreet) / (DOUBLE)(nNt - nNtt + nUser - nUsert);
	nStr = DWORD(100.0 - nHave * 100);
	nFreet = nFree;
	nNtt = nNt;
	nUsert = nUser;
}

获取物理内存使用率:

DWORD CMyTaskManDlg::GetMemState()
{
	MEMORYSTATUSEX nStatex;

	nStatex.dwLength = sizeof(nStatex);

	GlobalMemoryStatusEx(&nStatex);

	DOUBLE nAll = (DOUBLE)nStatex.ullTotalPhys / 1048576;
	DOUBLE nHave = (DOUBLE)nStatex.ullAvailPhys / 1048576;
	return (DWORD)((nAll - nHave) / nAll * 100);

}

5. 设置定时器,每隔一段时间获取系统参数并显示

在初始化函数OnInitDialog()中开启定时器

SetTimer(0, 250, NULL); //设置定时器每250ms产生一个随机数

void CMyTaskManDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	int nRandom = 0;
	DWORD nNum = GetMemState();
	GetCpuState(nRandom);
	m_ShowCPU.SetPos(nRandom);
	m_ShowMemory.SetPos(nNum);

	CDialogEx::OnTimer(nIDEvent);
}

6. 最终运行结果如下:

Win10 VS2013 ************************************************ * BOOL GetDiskSpaceInfo(LPCSTR pszDrive * 功能 根据输入的驱动器,获取磁盘总容量 * 空闲空间、簇数量等磁盘信息 * 参数 驱动器根路径,比如“D:\”。 ************************************************ * void GetTime() * 功能 获取并显示本地与系统时间 ************************************************ * void GetLang() * 功能 获取并显示系统的默认语言 ************************************************ * void ShowVersionInfo() * 功能 获取并显示系统版本信息 ************************************************ * void ShowSystemInfo() * 功能 获取并显示硬件相关信息 ************************************************ *void GetFolders() * 功能 获取系统目录等信息 ************************************************ *void WINAPI EnumProcess1() * 功能 调用EnumProcess遍历进程 * 并调用ListProcessModules1函数和 * ListProcessThreads函数列举模块 * 和线程 ************************************************ * VOID ListProcessModules1( DWORD dwPID ) * 功能 调用EnumProcessModules函数 * 列举和显示进程加载的模块 * * 参数 DWORD dwPID 进程PID ************************************************ * VOID ListProcessThreads( DWORD dwPID ) * 功能 调用Thread32First和Thread32Next * 显示一个进程的线程 * * 参数 DWORD dwPID 进程PID ************************************************ * VOID PrintError( LPTSTR msg ) * 功能 打印出错信息 * * 参数 LPTSTR msg ************************************************ * void GetDriveInfo( LPCTSTR lpRootPath) * 功能 返 回 指 定 驱 动 器 的 类 型。 * * 参数 lpRootPathName ************************************************ * void GetSystemMetric(int nIndex) * 功能 返 回 显 示 器 分 辨 率。 * * 参数 ************************************************ * void GetKeyboardInfo() * 功能 返回键盘类型。 * * 参数 *************************************************
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值