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
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" />
2021年8月13日11:50:20 望技术有成后能回来看见自己的脚步