Duilib自绘圆形进度条



CircleProgressUI.h

#pragma once

namespace DuiLib
{
	class CCircleProgressUI :
		public CProgressUI
	{
	public:
		CCircleProgressUI(void);
		~CCircleProgressUI(void);

		void SetCircular(BOOL bCircular = TRUE);
		void SetClockwiseRotation(BOOL bClockwise = TRUE);
		void SetCircleWidth(DWORD dwCircleWidth);
		void SetBgColor(DWORD dwBgColor);
		DWORD GetBgColor() const;
		void SetFgColor(DWORD dwBgColor);
		DWORD GetFgColor() const;
		void SetIndicator(LPCTSTR lpIndicatorImage);
		void SetEnableCircleEffect(BOOL bEnableCircleEffect = FALSE);
		void SetCircleGradientColor1(DWORD dwColor);
		void SetCircleGradientColor2(DWORD dwColor);
		void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
		void PaintBkColor(HDC hDC);

	private:
		BOOL		m_bCircular;
		BOOL		m_bClockwise;
		DWORD	m_dwCircleWidth;
		DWORD	m_dwBgColor;
		DWORD	m_dwFgColor;
		BOOL		m_bEnableCircleEffect;
		DWORD	m_dwGradientColor1;
		DWORD	m_dwGradientColor2;
		Image*		m_pIndicator;
		CString     m_sIndicatorImage;
	};

}		//namespace Duilib

CircleProgressUI.cpp

#include "StdAfx.h"
#include "CircleProgressUI.h"

namespace DuiLib
{
	extern int GetEncoderClsid(const WCHAR* format, CLSID *pClsid);

	Color ARGB2Color(DWORD dwColor)
	{
		return Color(HIBYTE((dwColor)>>16), GetBValue(dwColor), GetGValue(dwColor), GetRValue(dwColor));
	}

	CCircleProgressUI::CCircleProgressUI(void)
	: m_bCircular(FALSE)
	, m_bClockwise(TRUE)
	, m_dwCircleWidth(10.0)
	, m_dwFgColor()
	, m_dwBgColor()
	, m_bEnableCircleEffect(FALSE)
	, m_dwGradientColor1()
	, m_dwGradientColor2()
	, m_sIndicatorImage(L"")
	, m_pIndicator(NULL)
	{

	}

	CCircleProgressUI::~CCircleProgressUI(void)
	{
		if (m_pIndicator)
		{
			delete m_pIndicator;
		}
	}

	void CCircleProgressUI::SetCircular(BOOL bCircular /* = TRUE */)
	{
		m_bCircular = bCircular;
		Invalidate();
	}

	void CCircleProgressUI::SetClockwiseRotation(BOOL bClockwise)
	{
		if (bClockwise != m_bClockwise)
		{
			m_bClockwise = bClockwise;
			if (m_pIndicator)
			{
				//已经旋转了图片,旋转到相反的方向
				m_pIndicator->RotateFlip(Rotate180FlipNone);
			}
			
		}
	}

	void CCircleProgressUI::SetCircleWidth(DWORD dwCircleWidth)
	{
		m_dwCircleWidth = dwCircleWidth;
		Invalidate();
	}

	void CCircleProgressUI::SetBgColor(DWORD dwBgColor)
	{
		m_dwBgColor = dwBgColor;
		Invalidate();
	}

	DWORD CCircleProgressUI::GetBgColor() const
	{
		return m_dwBgColor;
	}

	void CCircleProgressUI::SetFgColor(DWORD dwFgColor)
	{
		m_dwFgColor = dwFgColor;
		Invalidate();
	}

	DWORD CCircleProgressUI::GetFgColor() const
	{
		return m_dwFgColor;
	}

	void CCircleProgressUI::SetIndicator(LPCTSTR lpIndicatorImage)
	{
		ASSERT(lpIndicatorImage);
		if (m_sIndicatorImage != lpIndicatorImage)
		{		
			m_sIndicatorImage = lpIndicatorImage;
			const TImageInfo* imgInfo = GetManager()->GetImageEx(m_sIndicatorImage);
			BITMAP bmp;
			GetObject(imgInfo->hBitmap, sizeof(BITMAP), &bmp);

			m_pIndicator = new Bitmap(imgInfo->nX, imgInfo->nY, imgInfo->nX * 4, PixelFormat32bppARGB, (BYTE*)bmp.bmBits);
			Status state = m_pIndicator->GetLastStatus();
			if (Ok == state)
			{
				// 假定图片指向上
				m_pIndicator->RotateFlip(m_bClockwise ? Rotate90FlipNone : Rotate270FlipNone);
				Invalidate();
			}		
		}
	}

	void CCircleProgressUI::SetEnableCircleEffect(BOOL bEnableCircleEffect)
	{
		m_bEnableCircleEffect = bEnableCircleEffect;
	}

	void CCircleProgressUI::SetCircleGradientColor1(DWORD dwColor)
	{
		m_dwGradientColor1 = dwColor;
		Invalidate();
	}

	void CCircleProgressUI::SetCircleGradientColor2(DWORD dwColor)
	{
		m_dwGradientColor2 = dwColor;
		Invalidate();
	}

	void CCircleProgressUI::PaintBkColor(HDC hDC)
	{
		CProgressUI::PaintBkColor(hDC);
		if (m_bCircular)
		{
			if( m_nMax <= m_nMin ) m_nMax = m_nMin + 1;
			if( m_nValue > m_nMax ) m_nValue = m_nMax;
			if( m_nValue < m_nMin ) m_nValue = m_nMin;

			int direction = m_bClockwise ? 1 : -1;
			Gdiplus::REAL bordersize = 1.0;
			Graphics graphics( hDC );
			graphics.SetSmoothingMode(SmoothingModeAntiAlias);

			// 圆形中心
			PointF center;
			center.X = m_rcItem.left + (m_rcItem.right - m_rcItem.left) / 2;
			center.Y = m_rcItem.top + (m_rcItem.bottom - m_rcItem.top) / 2;

			// 控件矩形内的最大正方形的边界
			int side = min(m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top);
			RectF rcBorder;
			rcBorder.X = center.X - side / 2;
			rcBorder.Y = center.Y - side / 2;
			rcBorder.Width = side;
			rcBorder.Height = side;

			// 进度弧形的边界
			Gdiplus::RectF outer = rcBorder;
			if (m_pIndicator)
			{
				outer.Inflate( -1.0F * m_pIndicator->GetWidth() / 2, -1.0F * m_pIndicator->GetWidth() / 2);
			}
			else
			{
				outer.Inflate( -0.5 * m_dwCircleWidth - m_nBorderSize, -0.5 * m_dwCircleWidth - m_nBorderSize );		
			}

			outer.Inflate( -1.0F, -1.0F );

			Pen borderPen(Color::White, bordersize);
			Pen bgPen(m_dwBgColor, m_dwCircleWidth);			
			
			//graphics.DrawEllipse(&borderPen, outer);		
			
			RectF rcArk;
			rcArk.X = outer.X + outer.Width / 2 - m_dwCircleWidth / 2;
			rcArk.Y = outer.Y - m_dwCircleWidth / 2;
			rcArk.Width = rcArk.Height = m_dwCircleWidth;

			if (!m_bEnableCircleEffect)
			{
				Pen fgPen(m_dwFgColor, m_dwCircleWidth);
				graphics.DrawArc(&bgPen, outer, 270, 360);
				graphics.DrawArc(&fgPen, outer, 270, direction * 360 * (m_nValue - m_nMin) / (m_nMax - m_nMin));
			}
			else
			{
				REAL factors[4]={ 0.0f, 0.9f, 0.0f };  
				REAL position[4]={ 0.0f, 0.5f, 1.0f };  

				LinearGradientBrush lgbrush(rcBorder, ARGB2Color(m_dwGradientColor1), ARGB2Color(m_dwGradientColor2), LinearGradientModeVertical);  
				lgbrush.SetBlend(factors, position, 3); 
				//graphics.FillRectangle(&lgbrush, rcBorder); 
				graphics.DrawArc(&bgPen, outer, 270, 360);

				Pen fgPen(&lgbrush, m_dwCircleWidth);
				graphics.DrawArc(&fgPen, outer, 270, direction * 360 * (m_nValue - m_nMin) / (m_nMax - m_nMin));
			}	

			Matrix matrix;
			matrix.RotateAt(direction * 360 * (m_nValue - m_nMin) / (m_nMax - m_nMin), center, MatrixOrderAppend);
			graphics.SetTransform(&matrix);			

			if (m_pIndicator)
			{
				RectF rectf;
				rectf.X = center.X - m_pIndicator->GetWidth() / 2;
				rectf.Y = outer.Y + bordersize / 2 - m_pIndicator->GetHeight() / 2;
				rectf.Width = m_pIndicator->GetWidth();
				rectf.Height = m_pIndicator->GetHeight();
				graphics.DrawImage(m_pIndicator, rectf);
			}
		}
	}

	void CCircleProgressUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
	{
		if( _tcscmp(pstrName, _T("circular")) == 0 ) {
			SetCircular(_tcscmp(pstrValue, _T("true")) == 0);
		}
		else if( _tcscmp(pstrName, _T("clockwise")) == 0 ) {
			SetClockwiseRotation(_tcscmp(pstrValue, _T("true")) == 0);
		}
		else if( _tcscmp(pstrName, _T("circlewidth")) == 0 ) SetCircleWidth(_ttoi(pstrValue));
		else if( _tcscmp(pstrName, _T("bgcolor")) == 0 ) {
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetBgColor(clrColor);
		}
		else if( _tcscmp(pstrName, _T("fgcolor")) == 0 )	{
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetFgColor(clrColor);
		}
		else if (_tcscmp(pstrName, _T("indicator")) == 0)
		{
			SetIndicator(pstrValue);
		}
		else if( _tcscmp(pstrName, _T("enablecircleeffect")) == 0 ) {
			SetEnableCircleEffect(_tcscmp(pstrValue, _T("true")) == 0);
		}
		else if( _tcscmp(pstrName, _T("gradientcolor1")) == 0 )	{
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetCircleGradientColor1(clrColor);
		}
		else if( _tcscmp(pstrName, _T("gradientcolor2")) == 0 )	{
			if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
			LPTSTR pstr = NULL;
			DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
			SetCircleGradientColor2(clrColor);
		}
		else CProgressUI::SetAttribute(pstrName, pstrValue);
	}

}		// namespace Duilib

测试代码:

void CMainFrame::OnClick(TNotifyUI& msg)
{
	CDuiString sCtrlName = msg.pSender->GetName();

        if (sCtrlName == _T("start"))
	{
		CCircleProgressUI* progress = static_cast<CCircleProgressUI*>(m_PaintManager.FindControl(L"progress1"));
		progress->SetValue(1);
		CString sAttrs;
		bool bChecked = static_cast<CCheckBoxUI*>(m_PaintManager.FindControl(L"direction"))->GetCheck();
		sAttrs.Format(L"clockwise=\"%s\"", bChecked ? L"true" : L"false");
		progress->ApplyAttributeList(sAttrs);

		progress = static_cast<CCircleProgressUI*>(m_PaintManager.FindControl(L"progress2"));
		progress->SetValue(1);
		bChecked = static_cast<CCheckBoxUI*>(m_PaintManager.FindControl(L"direction"))->GetCheck();
		sAttrs.Format(L"clockwise=\"%s\"", bChecked ? L"true" : L"false");
		progress->ApplyAttributeList(sAttrs);
		m_PaintManager.SetTimer(m_PaintManager.GetRoot(), IDT_PROGRESS, 100);
	}
}

void CMainFrame::OnTimer(TNotifyUI& msg)
{
    switch (msg.wParam)
    {
    case IDT_PROGRESS:
        {
            CCircleProgressUI* progress = static_cast<CCircleProgressUI*>(m_PaintManager.FindControl(L"progress1"));
            progress->SetValue(progress->GetValue() + 1);
            CString percent;
            percent.Format(L"%d%%", 100 * (progress->GetValue() - progress->GetMinValue()) / (progress->GetMaxValue() - progress->GetMinValue()));
            progress->SetText(percent);

            progress = static_cast<CCircleProgressUI*>(m_PaintManager.FindControl(L"progress2"));
            progress->SetValue(progress->GetValue() + 1);
            percent.Format(L"%d%%", 100 * (progress->GetValue() - progress->GetMinValue()) / (progress->GetMaxValue() - progress->GetMinValue()));
            progress->SetText(percent);
        }
    default:
        ;        
    }
}

<CircleProgress name="progress1" circular="true" indicator="飞机.png" clockwise="false" enablecircleeffect="true" gradientcolor1="#FFFFFFFF" gradientcolor2="#FF0000FF" width="250" height="250" circlewidth="6" text="" min="1" max="100" value="10" bgcolor="#FFF8A09F" fgcolor="#FF9DEDF8" gradient="false" bordersize="1" bordercolor="#FFFFFF00" valign="vcenter" textcolor="0xFFFFFFFF" font="2" />


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值