概述:
代码实现如下:
#pragma once;
#pragma warning(disable:4995 4819)
#include "QsInclude.h"
#include <vector>
using namespace std;
/*************************进度Style定义****************/
#define QS_PBS_SOLD 0x00000001 //实心进度条
#define QS_PBS_BLOCK 0x00000002 //块状进度条
#define QS_PBS_TXT 0x00000100 //自绘时文字显示进度
#define QS_PBS_RANGE 0x00000200 //绘制比例进度条
#define QS_PBS_IMAGE 0x00001000 //背景和前景图片来显示进度条
#define QS_PBS_COLOR 0x00002000 //背景和前景用颜色来显示进度条
#define QS_PBS_SYSTEM 0x00004000 //不自绘,使用系统的默认特性
/**********************************************************/
typedef struct RangeClr
{
Color clr;
float rangepos;
}RangeClrName;
class CQSProgressBar :
public CWindowImpl<CQSProgressBar, CProgressBarCtrl>,
public CImageMgrCtrlBase< CQSProgressBar>
{
typedef CWindowImpl< CQSProgressBar, CProgressBarCtrl > theBaseClass;
typedef CImageMgrCtrlBase< CQSProgressBar> theImageCtrlBaseClass;
private:
typedef struct stFONT
{
TCHAR szFamilyName[LF_FACESIZE]; // 字体名称, 如:宋体、微软雅黑等
float fSize; // 字体大小
FontStyle nStyle; // 字体类型
Unit unit; // 字体的计量单位
} FONT;
FONT m_FontTxt; //显示进度百分比的字体
COLORREF m_crBK; // QS_PROBAR_STYLE_COLOR样式的文字颜色
Color m_crFGfront; // QS_PROBAR_STYLE_COLOR样式的前景色 前景色为渐变色
Color m_crFGend; // QS_PROBAR_STYLE_COLOR样式的前景色
COLORREF m_crtxt; // QS_PROBAR_STYLE_COLOR样式的背景色
DWORD m_QsStyle; //QS的自绘的样式
float FrontX;
float EndX;
vector<RangeClrName> m_rangeVct; //每部分比例
LinearGradientMode m_LGMode; //渐变方向
public:
BEGIN_MSG_MAP( CQSProgressBar )
MESSAGE_HANDLER( WM_PAINT, OnPaint )
MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBKGnd )
CHAIN_MSG_MAP( theImageCtrlBaseClass )
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
/**
*@method CQSProgressBar
*@brief CQSProgressBar类构造函数
*
*@return
*/
CQSProgressBar()
{
m_uFirstPos = CONTROL_PBS_FIRST;
m_uLastPos = CONTROL_PBS_LAST;
SetQSFont( _T("宋体"), 10, FontStyleRegular, UnitPoint );
m_crBK = RGB(255, 255, 255);
m_crFGfront = Color(220,0,188,40);
m_crFGend = Color(100,0, 188, 100);
m_crtxt = RGB(0, 255, 0);
m_QsStyle = QS_PBS_SYSTEM;
EndX = FrontX = 5;
m_LGMode =LinearGradientModeVertical;
}
/**
*@method ~CQSProgressBar
*@brief CQSProgressBar析构造函数
*
*@return
*/
virtual ~CQSProgressBar()
{
}
/**
*@method Create
*@brief 通过Create来创建窗口。
*
*@param HWND hWndParent
*@param ATL::_U_RECT rect = NULL
*@param LPCTSTR szWindowName = NULL
*@param DWORD dwStyle = 0
*@param DWORD dwExStyle = 0
*@param ATL::_U_MENUorID MenuOrID = 0U
*@param LPVOID lpCreateParam = NULL
*@return HWND
*/
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return theBaseClass::Create( hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
/**
*@method SetFrontorEnd
*@brief 设置前景图片的圆角的长度
*
*@param float fFront
*@param float fEnd
*@return void
*/
void SetFrontorEnd(float fFront,float fEnd)
{
FrontX = fFront;
EndX = fEnd;
}
/**
*@method SetFrontX
*@brief SetFrontX设置前景图片的圆角的长度
*
*@param float fFront
*@return void
*/
void SetFrontX(float fFront)
{
FrontX = fFront;
}
/**
*@method SetEndx
*@brief SetEndx设置前景图片的圆角最后的长度
*
*@param float fEnd
*@return void
*/
void SetEndx(float fEnd)
{
EndX = fEnd;
}
/**
*@method SubclassWindow
*@brief 类对象关联
*
*@param HWND hWnd 对象句柄
*@return BOOL 成功返回TRUE,失败返回FALSE
*/
BOOL SubclassWindow( HWND hWnd )
{
BOOL bRet = theBaseClass::SubclassWindow( hWnd );
ModifyStyleEx( WS_EX_APPWINDOW, 0 );
return bRet;
}
/**
*@method SetQSFont
*@brief 设置字体进度条显示字体
*
*@param TCHAR *szName 字体名称
*@param float fSize 字体大小
*@param FontStyle style 字体style
*@param Unit unit 字体显示单元
*@return BOOL 成功返回TRUE,失败返回FALSE
*/
BOOL SetQSFont( TCHAR *szName, float fSize, FontStyle style, Unit unit )
{
_tcscpy_s( m_FontTxt.szFamilyName, LF_FACESIZE, szName );
m_FontTxt.fSize = fSize;
m_FontTxt.nStyle = style;
m_FontTxt.unit = unit;
return TRUE;
}
/**
*@method SetForColor
*@brief 设置QS_PROBAR_STYLE_COLOR
*
*@param Color crFGfront 设置前景的颜色1
*@param Color crFGend 设置前景的颜色2
*@param LinearGradientMode LGMode 的样式下的前景颜色
*@return void
*/
void SetForColor( Color crFGfront,Color crFGend,LinearGradientMode LGMode)
{
m_crFGfront = crFGfront;
m_crFGend = crFGend;
m_LGMode = LGMode;
}
/**
*@method SetBkColor
*@brief 设置QS_PROBAR_STYLE_COLOR 的样式下的背景颜色
*
*@param COLORREF bkcolor 设置背景景的颜色
*@return void
*/
void SetBkColor(COLORREF bkcolor)
{
m_crBK = bkcolor;
}
/**
*@method SetQSWindowsStyle
*@brief 设置进度条的样式下的背景颜色
*
*@param DWORD nStyle 窗口的自绘样式
*@return void
*/
void SetQSWindowsStyle(DWORD nStyle)
{
m_QsStyle = nStyle;
}
void SetPosRange(const vector<RangeClr> rangeClr)
{
m_rangeVct.clear();
m_rangeVct = rangeClr;
}
protected:
/**
*@method DrawRect
*@brief 进度条的矩形区域绘制
*
*@param Graphics* pGraphics 绘图对象
*@param Rect r 绘图区域
*@param Color ulclr 颜色值内圈
*@param Color brclr 外圈颜色值
*@param int width 外矩形框的宽度
*@return void 成功返回TRUE,失败返回FALSE
*/
void DrawRect(Graphics* pGraphics, Rect r, Color ulclr, Color brclr, int width)
{
int i = 0;
int left = 0;
int top =0;
int bottom =0;
int right =0;
// disable smoothing mode
SmoothingMode oldMode = pGraphics->GetSmoothingMode();
pGraphics->SetSmoothingMode(SmoothingModeNone);
// define the upper left pen
Pen ulpen(ulclr, 1);
ulpen.SetAlignment(PenAlignmentCenter);
// define the bottom right pen
Pen brpen(brclr, 1);
brpen.SetAlignment(PenAlignmentCenter);
// not sure why
Rect rc(r);
for(i = 0; i < width; i++)
{
left = rc.X; top = rc.Y; bottom = rc.GetBottom()-1; right = rc.GetRight()-1;
if((i%2)==0)
{
// left
pGraphics->DrawLine(&ulpen, left, top, left, bottom);
// top
pGraphics->DrawLine(&ulpen, left, top, right, top);
// right
pGraphics->DrawLine(&ulpen, right, top+1, right, bottom);
// bottom
pGraphics->DrawLine(&ulpen, left+1, bottom, right, bottom);
}
else
{
// left
pGraphics->DrawLine(&brpen, left, top, left, bottom);
// top
pGraphics->DrawLine(&brpen, left, top, right, top);
// right
pGraphics->DrawLine(&brpen, right, top+1, right, bottom);
// bottom
pGraphics->DrawLine(&brpen, left+1, bottom, right, bottom);
}
rc.Inflate(-1, -1);
}
// restore smoothing mode
pGraphics->SetSmoothingMode(oldMode);
}
/**
*@method DrawNormalProgressBar
*@brief 绘制普通颜色填充的进度条函数
*
*@return void
*/
void DrawNormalProgressBar()
{
// 获得作图区域
CRect rtBar;
GetWindowRect(&rtBar);
WTL::CPaintDC paintDC( m_hWnd );
paintDC.SetBkMode( TRANSPARENT );
WTL::CDC dc;
dc.CreateCompatibleDC( paintDC.m_hDC );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( paintDC.m_hDC, rtBar.Width(), rtBar.Height() );
HBITMAP hOldBmp = dc.SelectBitmap( memBitmap );
dc.SetBkMode( TRANSPARENT );
Graphics graph( dc.m_hDC );
// 画背景
SolidBrush lgbr(Color(255, GetRValue(m_crBK), GetGValue(m_crBK), GetBValue(m_crBK)));
graph.FillRectangle(&lgbr, 0, 0, rtBar.Width(), rtBar.Height());
Image *pImage = GetImage( CONTROL_PBS_BACKIMG );
if(pImage != NULL)
{
graph.DrawImage( pImage,RectF ( (REAL)0.0, (REAL)0.0, (REAL)rtBar.Width(), (REAL)rtBar.Height() ),0, (REAL)0, (REAL)pImage->GetWidth(), (REAL)pImage->GetHeight(), UnitPixel );
}
Rect rect(0,0,rtBar.Width(),rtBar.Height());
DrawRect(&graph,rect,Color(200,190,190,190),Color(240,104, 104, 104),1); //绘外框区域
// 画进度
UINT pos = GetPos();
int maxPos = 0;
int minPos = 0;
GetRange( minPos, maxPos );
float fRatio = ( (float) pos - (float )minPos) / ( (float)maxPos - (float )minPos );
//SolidBrush sbFG(Color(160, GetRValue(m_crFG), GetGValue(m_crFG), GetBValue(m_crFG)));
REAL positions[] = { 0.0f, 1.0f};
Color colors[2] ={m_crFGfront,m_crFGend};
Rect rectF(rtBar.left,rtBar.top,rtBar.Width(),rtBar.Height());
//LinearGradientBrush lgbr(rectF, Color(RGB(255,255,255)), Color(RGB(255,255,255)), m_LGMode);
//lgbr.SetInterpolationColors(colors, positions, 2);
REAL rWidth = 10;
//REAL rHeight = (REAL)(rtBar.Height());
RectF rtfFG;
rtfFG.X = 0;
rtfFG.Y = 0;
if(m_QsStyle&QS_PBS_SOLD)
{
rtfFG.Width = (rtBar.Width()) * fRatio;
rtfFG.Height = (REAL)rtBar.Height() - 4;
graph.FillRectangle(&lgbr, rtfFG);
}
if(m_QsStyle&QS_PBS_BLOCK)
{
rtfFG.Width = (REAL)(rWidth * 0.8);
rtfFG.Height = (REAL)(rtBar.Height())-4;
while((rtfFG.X + rtfFG.Width) < (rtBar.Width() * fRatio))
{
graph.FillRectangle(&lgbr, rtfFG);
rtfFG.X += rWidth;
}
if(pos!=0) //多绘一个
{
graph.FillRectangle(&lgbr, rtfFG);
}
}
if(m_QsStyle&QS_PBS_TXT)
{
DrawText(pos,maxPos,graph,rtBar);
}
if (m_QsStyle&QS_PBS_RANGE)
{
rtfFG.X = 1;
rtfFG.Y = 1;
//绘制比例进度条
for (vector<RangeClr>::iterator pos = m_rangeVct.begin();pos != m_rangeVct.end();pos ++)
{
colors[0] = pos->clr;
lgbr.SetColor(colors[0]);
//lgbr.SetInterpolationColors(colors,positions,2);
rtfFG.Width = (rtBar.Width())*(pos->rangepos);
rtfFG.Height = (REAL)rtBar.Height() - 1;
graph.FillRectangle(&lgbr,rtfFG);
rtfFG.X += (int)(rtBar.Width())*(pos->rangepos);
}
}
graph.ReleaseHDC( dc.m_hDC );
// 提交图像
paintDC.BitBlt( 0, 0, rtBar.Width(), rtBar.Height(), dc.m_hDC, 0, 0, SRCCOPY );
dc.SelectBitmap( hOldBmp );
memBitmap.DeleteObject();
dc.DeleteDC();
}
/**
*@method DrawImageProgressBar
*@brief 绘制图片填充的进度条函数
*
*@return void
*/
void DrawImageProgressBar()
{
CRect rtBar;
GetWindowRect(&rtBar);
WTL::CPaintDC paintDC( m_hWnd );
paintDC.SetBkMode( TRANSPARENT );
WTL::CDC dc;
dc.CreateCompatibleDC( paintDC.m_hDC );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( paintDC.m_hDC, rtBar.Width(), rtBar.Height() );
HBITMAP hOldBmp = dc.SelectBitmap( memBitmap );
dc.SetBkMode( TRANSPARENT );
::SendMessage( GetParent(), WM_DRAWBKGNDUI, ( WPARAM )dc.m_hDC, ( LPARAM )m_hWnd);
Graphics graph( dc.m_hDC );
// 画背景
ColorMatrix HotMat = { 1.05f, 0.00f, 0.00f, 0.00f, 0.00f,
0.00f, 1.05f, 0.00f, 0.00f, 0.00f,
0.00f, 0.00f, 1.05f, 0.00f, 0.00f,
0.00f, 0.00f, 0.00f, 1.00f, 0.00f,
0.05f, 0.05f, 0.05f, 0.00f, 1.00f }; //光照矩阵
ImageAttributes ia;
ia.SetColorMatrix(&HotMat);
Image *pImage = GetImage( CONTROL_PBS_BACKIMG );
if(pImage != NULL)
{
graph.DrawImage( pImage,RectF ( (REAL)0.0, (REAL)0.0, (REAL)rtBar.Width(), (REAL)rtBar.Height() ),0, (REAL)0, (REAL)pImage->GetWidth(), (REAL)pImage->GetHeight(), UnitPixel );
}
// 画进度
int pos = GetPos();
int maxPos = 0;
int minPos = 0;
GetRange( minPos, maxPos );
if(maxPos>0) //只有MAX大于1是才绘制前景
{
/对除零处理
float fared= (float)maxPos - (float )minPos;
if(fared<0.0001) //
{
fared = 1.0f;
}
float fRatio = ( (float) pos - (float )minPos) / fared;
REAL rWidth = 10;
//REAL rHeight = (REAL)(rtBar.Height());
RectF rtfFG;
rtfFG.X = 0;
rtfFG.Y = 0;
Image *pImageFront = GetImage(CONTROL_PBS_FRONTIMGFRONT);
Image *pImageEnd = GetImage(CONTROL_PBS_FRONTIMGEND);
pImage = GetImage( CONTROL_PBS_FRONTIMG );
if(m_QsStyle&QS_PBS_SOLD)
{
if((pos>=1))
{
rtfFG.Width = (rtBar.Width()) * fRatio+FrontX;
if(pImageFront != NULL)
{
graph.DrawImage( pImageFront, RectF((REAL)0,(REAL)0,(REAL)FrontX,(REAL)rtBar.Height()), 0.0, 0.0, (REAL)pImageFront->GetWidth(), ( float ) pImageFront->GetHeight(), UnitPixel,&ia);
}
}
if((pos>2&&pos<maxPos)||(pos==maxPos))
{
rtfFG.X = rtfFG.X +FrontX;
rtfFG.Width = (REAL)((rtBar.Width()) * fRatio-EndX*1.5);
rtfFG.Height = (REAL)rtBar.Height();
if(pImage != NULL)
{
graph.DrawImage( pImage, rtfFG, 0.0, 0.0, (REAL)pImage->GetWidth(), ( float ) pImage->GetHeight(), UnitPixel,&ia );
}
}
if(pos==maxPos)
{
if(pImageEnd != NULL)
{
graph.DrawImage( pImageEnd, RectF( (REAL)(rtBar.Width()) -EndX,(REAL)0,EndX,(REAL)rtBar.Height()), 0.0, 0.0, (REAL)pImageEnd->GetWidth(), ( float ) pImageEnd->GetHeight(), UnitPixel ,&ia);
}
}
}
if(m_QsStyle&QS_PBS_BLOCK)
{
if(pos>=1)
{
rtfFG.Width = (rtBar.Width()) * fRatio+FrontX;
graph.DrawImage( pImageFront, RectF((REAL)0,(REAL)0,FrontX,(REAL)rtBar.Height()), 0.0, 0.0, (REAL)pImageFront->GetWidth(), ( float ) pImageFront->GetHeight(), UnitPixel );
rtfFG.X = rtfFG.X+FrontX;
rtfFG.X += 2;
}
rtfFG.Width = (REAL)(rWidth * 0.8);
rtfFG.Height = (REAL)(rtBar.Height());
while((rtfFG.X + rtfFG.Width) < (rtBar.Width() * fRatio))
{
if(pImageFront != NULL)
{
graph.DrawImage( pImage, rtfFG, 0.0, 0.0, (REAL)pImage->GetWidth(), ( float ) pImage->GetHeight(), UnitPixel);
rtfFG.X += rWidth;
}
}
if(pos==maxPos)
{
if(pImageEnd != NULL)
{
graph.DrawImage( pImageEnd, RectF(float(rtfFG.X),float(0),FLOAT(rtBar.Width()-rtfFG.X),(REAL)rtBar.Height()), 0.0, 0.0, (REAL)pImageEnd->GetWidth(), ( float ) pImageEnd->GetHeight(), UnitPixel );
}
}
}
if(m_QsStyle&QS_PBS_TXT)
{
DrawText(pos,maxPos,graph,rtBar);
}
graph.ReleaseHDC( dc.m_hDC );
}
//提交图像
paintDC.BitBlt( 0, 0, rtBar.Width(), rtBar.Height(), dc.m_hDC, 0, 0, SRCCOPY );
dc.SelectBitmap( hOldBmp );
memBitmap.DeleteObject();
dc.DeleteDC();
}
/**
*@method DrawText
*@brief 绘制进度条的百分比字体只是对
*
*@param int pos 当前进度条的位置
*@param int Maxpos 进度条的最大值
*@param Graphics& graph 绘图对象
*@param CRect rect 绘图区域
*@return void
*/
void DrawText(int pos,int Maxpos,Graphics& graph,CRect rect)
{
Gdiplus::Font font( m_FontTxt.szFamilyName, m_FontTxt.fSize, m_FontTxt.nStyle,m_FontTxt.unit);
StringFormat strFormat;
strFormat.SetAlignment( StringAlignmentNear ); // 设置横向对齐方式
strFormat.SetLineAlignment( StringAlignmentCenter ); // 设置纵向对齐方式
float fPos = float(pos);
int iPcent = int(float (fPos/Maxpos)*100);
CString strTxt = _T("");
strTxt.Format(_T( "%d" ),iPcent);
strTxt =strTxt+_T("%");
INT nLength = strTxt.GetLength();
SolidBrush brush( Color( 254, GetRValue(m_crtxt), GetGValue(m_crtxt), GetBValue(m_crtxt)) );
graph.DrawString(strTxt, (INT)nLength, &font,RectF( (float)rect.Width()/2, (float)0, (float)rect.Width(), (float)rect.Height() ),&strFormat, &brush );
}
/**
*@method OnPaint
*@brief 绘制消息函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
if(m_QsStyle&QS_PBS_SYSTEM)
{
return DefWindowProc( uMsg, wParam, lParam );
}
if(m_QsStyle&QS_PBS_COLOR)
{
DrawNormalProgressBar();
}
if(m_QsStyle&QS_PBS_IMAGE)
{
DrawImageProgressBar();
}
return 0;
}
/**
*@method OnEraseBKGnd
*@brief 背景绘制消息函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnEraseBKGnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
return DefWindowProc(uMsg, wParam, lParam);
}
};