MFC帶百分比的圓形進度條
阿新 • • 發佈:2019-02-02
#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); }