Duilib自绘圆形进度条(仿网易)

UICircleProgress.h

#pragma once
#include <GdiPlus.h>
#include <atlstr.h>

using namespace Gdiplus;

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;
		Gdiplus::Image* m_pIndicator;
		CString		m_sIndicatorImage;
	};
}

UICircleProgress.cpp

#include "stdafx.h"
#include "CircleProgress.h"
#include "shlwapi.h"

namespace ui
{

	CircleProgress::CircleProgress() :
		m_bCircular(true),
		m_bClockwise(true),
		m_nCircleWidth(1),
		m_dwBackgroundColor(0),
		m_dwForegroundColor(0),
		m_dwGradientColor(1),
		m_pIndicator(nullptr)
	{

	}

	void CircleProgress::SetAttribute(const std::wstring& srName, const std::wstring& strValue)
	{
		if (srName == _T("circular")) SetCircular(strValue == _T("true"));
		else if (srName == _T("circlewidth")) SetCircleWidth(_ttoi(strValue.c_str()));
		else if (srName == _T("indicator")) SetIndicator(strValue);
		else if (srName == _T("clockwise")) SetClockwiseRotation(strValue == _T("true"));
		else if (srName == _T("bgcolor")) {
			LPCTSTR pValue = strValue.c_str();
			while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
			SetBackgroudColor(pValue);
		}
		else if (srName == _T("fgcolor")) {
			LPCTSTR pValue = strValue.c_str();
			while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
			SetForegroudColor(pValue);
		}
		else if (srName == _T("gradientcolor")) {
			LPCTSTR pValue = strValue.c_str();
			while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
			SetCircleGradientColor(pValue);
		}
		else Progress::SetAttribute(srName, strValue);
	}

	void CircleProgress::PaintStatusImage(IRenderContext* pRender)
	{
		//Progress::PaintStatusImage(pRender);
		if (m_bCircular)
		{
			//目前IRenderContext还有很多GDI+接口未实现,暂时直接用gdi+画图了
			//以后可能会调整:需实现1、DrawArc  2、Pen增加brush(渐变)入参 3、可以自由设置Graphics属性
			int direction = m_bClockwise ? 1 : -1;   //旋转方向
			int bordersize = 1;          //弧度宽度目前使用1像素

			Gdiplus::Graphics graphics(pRender->GetDC());
			graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
			Gdiplus::Pen bgPen(m_dwBackgroundColor, m_nCircleWidth);
			// 圆形中心
			CPoint 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);
			//UiRect rcBorder;  仍然存在UiRect 到 RectF的转换,所以直接用gdi的RectF了
			Gdiplus::RectF rcBorder;
			rcBorder.X = center.x - side / 2;
			rcBorder.Y = center.y - side / 2;
			rcBorder.Width = 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_nCircleWidth, -0.5 * m_nCircleWidth);
			}
			outer.Inflate(-1, -1);


			if (m_dwGradientColor == 0)
			{
				//不使用渐变色,直接用前景色铺满
				Gdiplus::Pen fgPen(m_dwForegroundColor, m_nCircleWidth);
				graphics.DrawArc(&bgPen, outer, 270, 360);   //270从最上面开始递增,设为0的话,是最右边开始
				graphics.DrawArc(&fgPen, outer, 270, direction * 360 * (m_nValue - m_nMin) / (m_nMax - m_nMin));
			}
			else
			{
				Gdiplus::REAL factors[4] = { 0.0f, 0.4f, 0.6f, 1.0f };
				Gdiplus::REAL positions[4] = { 0.0f, 0.2f, 0.8f, 1.0f };

				Gdiplus::LinearGradientBrush lgbrush(rcBorder, m_dwForegroundColor, m_dwGradientColor, Gdiplus::LinearGradientModeVertical);
				lgbrush.SetBlend(factors, positions, 4);
				graphics.DrawArc(&bgPen, outer, 270, 360);
				Gdiplus::Pen fgPen(&lgbrush, m_nCircleWidth);
				graphics.DrawArc(&fgPen, outer, 270, direction * 360 * (m_nValue - m_nMin) / (m_nMax - m_nMin));

			}

			//画旋转指示器图标,需要用到矩阵
			if (m_pIndicator)
			{
				Gdiplus::Matrix matrix;
				matrix.RotateAt(direction * 360 * (m_nValue - m_nMin) / (m_nMax - m_nMin), Gdiplus::PointF(center.x, center.y), Gdiplus::MatrixOrderAppend);
				graphics.SetTransform(&matrix);
				Gdiplus::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 CircleProgress::ClearImageCache()
	{
		__super::ClearImageCache();
		if (m_pIndicator)
		{
			delete m_pIndicator;
			m_pIndicator = nullptr;
		}
	}

	void CircleProgress::SetCircular(bool bCircular /*= true*/)
	{
		m_bCircular = bCircular;
		Invalidate();
	}

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

		}
	}

	void CircleProgress::SetCircleWidth(int nCircleWidth)
	{
		m_nCircleWidth = nCircleWidth;
		Invalidate();
	}


	void CircleProgress::SetBackgroudColor(const std::wstring& strColor)
	{
		m_dwBackgroundColor = GlobalManager::GetTextColor(strColor);
		ASSERT(m_dwBackgroundColor != 0);
		Invalidate();
	}

	void CircleProgress::SetForegroudColor(const std::wstring& strColor)
	{
		m_dwForegroundColor = GlobalManager::GetTextColor(strColor);
		ASSERT(m_dwForegroundColor != 0);
		Invalidate();
	}

	void CCircleProgressUI::SetIndicator(LPCTSTR lpIndicatorImage)
	{
		ASSERT(lpIndicatorImage);
		if (m_sIndicatorImage != lpIndicatorImage)
		{
			m_sIndicatorImage = lpIndicatorImage;

			std::wstring imageResourcePath;
			std::wstring imagepath = m_sIndicatorImage;
			if (!::PathFileExistsW(imagepath.c_str())) 
			{
				CString strResourcePath = GetManager()->GetResourcePath();
				imageResourcePath = strResourcePath;
				imagepath = imageResourcePath + imagepath;
			}

			if (!::PathFileExistsW(imagepath.c_str())) {
				return;
			}


			m_pIndicator = new Gdiplus::Image(imagepath.c_str());

			Status state = m_pIndicator->GetLastStatus();
			if (Ok == state)
			{
				// 假定图片指向上
				m_pIndicator->RotateFlip(m_bClockwise ? Rotate90FlipNone : Rotate270FlipNone);
				Invalidate();
			}
		}
	}

	void CircleProgress::SetCircleGradientColor(const std::wstring& strColor)
	{
		m_dwGradientColor = GlobalManager::GetTextColor(strColor);
		ASSERT(m_dwGradientColor != 0);
		Invalidate();
	}

}

使用:

void CRichListWnd::OnSelectChanged( TNotifyUI &msg )
{
	if(msg.pSender->GetName() == _T("down_list"))
	{
		static_cast<CTabLayoutUI*>(m_PaintManager.FindControl(_T("tab_main")))->SelectItem(0);
	}
	else if(msg.pSender->GetName() == _T("down_his"))
	{
		static_cast<CTabLayoutUI*>(m_PaintManager.FindControl(_T("tab_main")))->SelectItem(1);

		CCircleProgressUI* progress = static_cast<CCircleProgressUI*>(m_PaintManager.FindControl(L"proName"));
		if (!progress)return;

		progress->SetValue(1);

		::SetTimer(m_hWnd, IDT_PROGRESS, 100, NULL);

	}
}
LRESULT CRichListWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	switch (wParam)
	{
	case IDT_PROGRESS:
	{
		CCircleProgressUI* progress = static_cast<CCircleProgressUI*>(m_PaintManager.FindControl(L"proName"));
		value = value % 100;
		progress->SetValue(value);

		TCHAR szBuffer[32] = { 0 };

		swprintf_s(szBuffer, _T("%d%%"), value);
		
		progress->SetText(szBuffer);
		value++;
	}
	default:
		break;
	}

	bHandled = false;
	return 0;
}

在duilib库"\Core\UIDefine.h" 添加:
在这里插入图片描述
在duilib库"\DuiLib\UIlib.h" 添加头文件
在这里插入图片描述

在duilib库"\Core\UIDlgBuilder.cpp" 找到函数CControlUI* CDialogBuilder::_Parse(CMarkupNode* pRoot, CControlUI* pParent, CPaintManagerUI* pManager)添加
在这里插入图片描述

logo_18x18.png
logo_18x18.png

xml

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

在这里插入图片描述

 202181311:50:20 望技术有成后能回来看见自己的脚步
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值