1. 程式人生 > >MFC帶百分比的圓形進度條

MFC帶百分比的圓形進度條

#pragma once
#include

using namespace Gdiplus;
// CCircleProgress

class CCircleProgress : public CStatic
{
	DECLARE_DYNAMIC(CCircleProgress)

public:
	CCircleProgress();
	virtual ~CCircleProgress();


public:
	ULONG_PTR gdiplusToken;
	Color* m_colors;
	int m_percent;
	int m_penWidth;
	CPoint m_centerPoint;
	int m_elementCount;
	int m_insideRadius;
	int m_outsideRadius;
	CRect m_rect;
	int m_offSet;
	CString m_strPercent;

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnPaint();
	void Init(CWnd* parentWnd,int nCount, int elementWidth, COLORREF color,CRect rect); 
	void SetPercent(int percent);
	void SetColors(COLORREF color);
	Color Darken(Color color, int percent);
	void SetCircleAppearance(int insideRadius, int outsideRadius);
	afx_msg void OnTimer(UINT_PTR nIDEvent);
	void StartProgress();
	void StopProgress();
};


// CircleProgress.cpp : 實現檔案
//

#include "stdafx.h"
#include "MFCApplication1.h"
#include "CircleProgress.h"
#include

#define  PI 3.1415926535897932384626433832795028
// CCircleProgress

IMPLEMENT_DYNAMIC(CCircleProgress, CStatic)

CCircleProgress::CCircleProgress()
{
	GdiplusStartupInput gdiplusStartupInput;
	
	//初始化GDI+
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	m_colors = NULL;
	m_percent = 0;
	m_penWidth = 0;
	m_centerPoint = 0;
	m_elementCount = 0;
	m_insideRadius = 0;
	m_outsideRadius = 0;
	m_rect = 0;
	m_offSet = 0;
	m_strPercent = L"0%";
}

CCircleProgress::~CCircleProgress()
{
	GdiplusShutdown(gdiplusToken);
}


BEGIN_MESSAGE_MAP(CCircleProgress, CStatic)
	ON_WM_PAINT()
	ON_WM_TIMER()
END_MESSAGE_MAP()



// CCircleProgress 訊息處理程式




void CCircleProgress::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	CDC memdc;
	memdc.CreateCompatibleDC(NULL);
	CBitmap memBitmap;
	memBitmap.CreateCompatibleBitmap(&dc, m_rect.Width(), m_rect.Height());
	memdc.SelectObject(memBitmap);
	memdc.FillSolidRect(CRect(0,0,m_rect.Width(),m_rect.Height()), RGB(240, 240, 240));

	Graphics graphics(memdc);
	graphics.SetSmoothingMode(SmoothingModeDefault);	//描邊時消除鋸齒

	byte byIncrement = (byte)(255 / 12);
	byte iPercent = 255;

	double angle = (double)360 / m_elementCount;


	Pen initPen(Darken(GetPixel(dc, 1, 1), 255), m_penWidth);
	initPen.SetStartCap(LineCapRound);	//設定線帽樣式
	initPen.SetEndCap(LineCapRound);
	for (int iCounter = 0; iCounter < m_elementCount; iCounter++)
	{
		Point startP, endP;
		startP.X = m_centerPoint.x + m_insideRadius * (float)cos((PI*(1 + iCounter)*angle) / 180);
		startP.Y = m_centerPoint.y + m_insideRadius * (float)sin((PI*(1 + iCounter)*angle) / 180);

		endP.X = m_centerPoint.x + m_outsideRadius * (float)cos((PI*(1 + iCounter)*angle) / 180);
		endP.Y = m_centerPoint.y + m_outsideRadius * (float)sin((PI*(1 + iCounter)*angle) / 180);
		

		graphics.DrawLine(&initPen, startP, endP);

	}

	for (int iCounter = 0; iCounter < m_elementCount; iCounter++)
	{
		Point startP, endP;
		startP.X = m_centerPoint.x + m_insideRadius * (float)cos((PI*(1 + iCounter)*angle) / 180);
		startP.Y = m_centerPoint.y + m_insideRadius * (float)sin((PI*(1 + iCounter)*angle) / 180);

		endP.X = m_centerPoint.x + m_outsideRadius * (float)cos((PI*(1 + iCounter)*angle) / 180);
		endP.Y = m_centerPoint.y + m_outsideRadius * (float)sin((PI*(1 + iCounter)*angle) / 180);
		int index = (iCounter + m_offSet) % m_elementCount;
		Pen pen(m_colors[index], m_penWidth);
		pen.SetStartCap(LineCapRound);	//設定線帽樣式
		pen.SetEndCap(LineCapRound);

		graphics.DrawLine(&pen, startP, endP);

	}

	//畫百分比
	Gdiplus::FontFamily fontFamily(L"宋體");
	Gdiplus::Font font(&fontFamily,20,FontStyleRegular,UnitPixel);
	StringFormat stringformat;
	stringformat.SetAlignment(StringAlignmentCenter);
	stringformat.SetLineAlignment(StringAlignmentCenter);
	SolidBrush brush(Color(255, 0x66, 0xcc, 0x66));
	graphics.DrawString(m_strPercent, -1, &font, RectF(0, 0, m_rect.Width(), m_rect.Height()), &stringformat, &brush);

	BitBlt(dc, 0, 0, m_rect.Width(), m_rect.Height(), memdc, 0, 0, SRCCOPY);
	
}

void CCircleProgress::Init(CWnd* parentWnd, int nCount, int elementWidth, COLORREF color, CRect rect)
{
	m_rect = rect;
	m_penWidth = elementWidth;
	m_centerPoint.SetPoint(rect.Width() / 2, rect.Height() / 2);
	m_elementCount = nCount;
	m_colors = new Color[nCount];
	SetColors(color);
	RECT rc;
	rc.top = rect.top; rc.bottom = rect.bottom; rc.left = rect.left; rc.right = rect.right;

	Create(L"", SS_OWNERDRAW | WS_CHILDWINDOW, rc, parentWnd);
	ShowWindow(SW_SHOW);
}

void CCircleProgress::SetPercent(int percent)
{
	m_percent = percent;
	m_strPercent.Format(L"%d%%", percent);
	if (percent == 100)
	{
		StopProgress();
	}
	else
	{
		RedrawWindow();
	}

}
void CCircleProgress::SetColors(COLORREF color)
{
	byte byteIncrement = byte(255 / m_elementCount);

	Color argb;
	argb.SetFromCOLORREF(color);
	for (int i = 0; i < m_elementCount; i++)
	{
		m_colors[i] = Darken(argb, byteIncrement*(i + 1));
	}

}

Color CCircleProgress::Darken(Color color, int percent)
{
	return Color(percent, color.GetR(), color.GetG(), color.GetB());
}

void CCircleProgress::SetCircleAppearance(int insideRadius, int outsideRadius)
{
	m_insideRadius = insideRadius;
	m_outsideRadius = outsideRadius;
	SetWindowPos(this, m_rect.left, m_rect.top, outsideRadius * 2 + 6, outsideRadius * 2 + 6, SWP_NOZORDER);
	m_rect = CRect(m_rect.left, m_rect.top,m_rect.left + outsideRadius * 2 + 6, m_rect.top + outsideRadius * 2 + 6);
	m_centerPoint = CPoint(m_rect.Width() / 2 , m_rect.Height() / 2 );

	Invalidate(TRUE);
}

void CCircleProgress::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == 1)
	{
		m_offSet = (m_offSet + 1) % m_elementCount;
		Invalidate(FALSE);
	}

	CStatic::OnTimer(nIDEvent);
}

void CCircleProgress::StartProgress()
{
	SetTimer(1, 200, NULL);
}
void CCircleProgress::StopProgress()
{
	KillTimer(1);
}