一个简单的进度条重绘,这个是基于MFC的CProgressCtrl做的
#if !defined(AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_)
#define AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// EnhProgressCtrl.h : header file
//
#include "MemDC.h"
/////////////////////////////////////////////////////////////////////////////
// CGradientProgressCtrl window
class CGradientProgressCtrl : public CProgressCtrl
{
// Construction
public:
CGradientProgressCtrl();
// Attributes
public:
// Attributes
void SetRange(int nLower, int nUpper);
int SetPos(int nPos);
int SetStep(int nStep);
int StepIt(void);
// Operations
public:
// Set Functions
void SetTextColor(COLORREF color) {m_clrText = color;}
void SetBkColor(COLORREF color) {m_clrBkGround = color;}
void SetStartColor(COLORREF color) {m_clrStart = color;}
void SetEndColor(COLORREF color) {m_clrEnd = color;}
// Show the percent caption
void ShowPercent(BOOL bShowPercent = TRUE) {m_bShowPercent = bShowPercent;}
// Get Functions
COLORREF GetTextColor(void) {return m_clrText;}
COLORREF GetBkColor(void) {return m_clrBkGround;}
COLORREF GetStartColor(void) {return m_clrStart;}
COLORREF GetEndColor(void) {return m_clrEnd;}
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGradientProgressCtrl)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CGradientProgressCtrl();
// Generated message map functions
protected:
void DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth);
int m_nLower, m_nUpper, m_nStep, m_nCurrentPosition;
COLORREF m_clrStart, m_clrEnd, m_clrBkGround, m_clrText;
BOOL m_bShowPercent;
//{{AFX_MSG(CGradientProgressCtrl)
afx_msg void OnPaint();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
#if 1 ///add zp 20170213
void Redrew();
#endif
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ENHPROGRESSCTRL_H__12909D73_C393_11D1_9FAE_8192554015AD__INCLUDED_)
实现
// GradientProgressCtrl.cpp : implementation file
// Download by http://www.codefans.net
#include "stdafx.h"
#include "GradientProgressCtrl.h"
#include "resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGradientProgressCtrl
extern CFont *g_DisplayFont32;
CGradientProgressCtrl::CGradientProgressCtrl()
{
//初始化
m_nLower = 0;
m_nUpper = 100;
m_nCurrentPosition = 0;
m_nStep = 10;
m_clrStart = COLORREF(RGB(0,255,0));
m_clrEnd = COLORREF(RGB(255,0,0));
m_clrBkGround = COLORREF(RGB(255, 255, 255));
m_clrText = COLORREF(RGB(0,0,0));
m_bShowPercent = FALSE;
}
CGradientProgressCtrl::~CGradientProgressCtrl()
{
}
BEGIN_MESSAGE_MAP(CGradientProgressCtrl, CProgressCtrl)
//{{AFX_MSG_MAP(CGradientProgressCtrl)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGradientProgressCtrl message handlers
void CGradientProgressCtrl::OnPaint()
{
#ifdef NEW_PROGRESS ///modify zp 20170213 18:30:20 之前使用的是纯颜色,修改后使用的是图片
//Redrew();
CPaintDC dc(this);
#else
CPaintDC dc(this); // device context for painting
//如果进度条的当前位置不正确,则渐变到背景色
if (m_nCurrentPosition <= m_nLower || m_nCurrentPosition > m_nUpper)
{
CRect rect;
GetClientRect(rect);
CBrush brush;
brush.CreateSolidBrush(RGB(255,255,255));
dc.FillRect(&rect, &brush);
VERIFY(brush.DeleteObject());
return;
}
//获得需要渐变的区域
CRect rectClient;
GetClientRect(&rectClient);
float maxWidth((float)m_nCurrentPosition/(float)m_nUpper * (float)rectClient.right);
//画渐变颜色
DrawGradient(&dc, rectClient, (int)maxWidth);
//如果需要显示百分数,则显示
if (m_bShowPercent)
{
CString percent;
percent.Format(_T("%.0f%%"), 100.0f*(float)m_nCurrentPosition/(float)m_nUpper);
dc.SetTextColor(RGB(0, 0, 0));
dc.SetBkMode(TRANSPARENT);
dc.SelectObject(g_DisplayFont32);
dc.DrawText(percent, &rectClient, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
}
#endif
}
#if 1 add zp 20170213
void CGradientProgressCtrl::Redrew()
{
PAINTSTRUCT ps;//声明一个绘画区域
CDC *pDC=BeginPaint(&ps);//把绘画区域选入设备上下文并开始
int AdrPos=GetPos();//获取进度条的进度位置
CString StrPos;//声明字符串,用于显示进度条的进度
StrPos.Format(_T("%d%%"),AdrPos);//把进度位置复制到StrPos
CRect ClientRC;
GetClientRect(&ClientRC);//获取客户区矩形
CSize CsText=pDC->GetTextExtent(StrPos);//获取显示StrPos的规模大小
int nX=(ClientRC.Width()-CsText.cx )/2;//获取显示字符串的X
int nY=(ClientRC.Height()-CsText.cy )/2;//获取显示字符串的Y
pDC->SetBkMode(TRANSPARENT);//设置背景模式为透明
int nMin,nMax;//声明进度条的最大最小限制
GetRange(nMin,nMax);//获取限制
double Every=(double)ClientRC.Width()/(nMax-nMin);//获取单位刻度
int Now=Every*AdrPos;//当前长度
CRect LeftRC,RightRC;//声明进度条区域和空白区域
LeftRC=RightRC=ClientRC;
LeftRC.right =Now;//进度条区域
RightRC.left =Now;//空白区域
CBitmap bitmap;
//bitmap.LoadBitmap(IDB_BITMAP_aqua);
bitmap.LoadBitmap(IDB_BITMAP_prg);
CBrush brushQueen(&bitmap);
pDC->FillRect(LeftRC,&brushQueen);//画进度条区域
pDC->FillRect(RightRC,&(CBrush)RGB(120,120,120));//画空白区域
pDC->SetTextColor(RGB(255,0,0));//设置文本颜色
//pDC->TextOutA(nX,nY,StrPos);//写文本
pDC->TextOut(nX,nY,StrPos);//写文本
ReleaseDC(pDC);//销毁设备上下文
EndPaint(&ps);//结束绘画区域绘画
// CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CWnd::OnPaint() for painting messages
}
#endif
//设置进度条范围
void CGradientProgressCtrl:: SetRange(int nLower, int nUpper)
{
m_nLower = nLower;
m_nUpper = nUpper;
m_nCurrentPosition = nLower;
CProgressCtrl::SetRange(nLower, nUpper);
}
//设置进度条的位置
int CGradientProgressCtrl:: SetPos(int nPos)
{
m_nCurrentPosition = nPos;
return (CProgressCtrl::SetPos(nPos));
}
//设置进度条的步长
int CGradientProgressCtrl:: SetStep(int nStep)
{
m_nStep = nStep;
return (CProgressCtrl::SetStep(nStep));
}
int CGradientProgressCtrl:: StepIt(void)
{
m_nCurrentPosition += m_nStep;
return (CProgressCtrl::StepIt());
}
//在适当区域画渐变颜色
void CGradientProgressCtrl::DrawGradient(CPaintDC *pDC, const RECT &rectClient, const int &nMaxWidth)
{
RECT rectFill;
float fStep;
CBrush brush;
CMemDC memDC(pDC);
//找到其实颜色和结束颜色之间的最大颜色值,决定渐变步长等
int r, g, b;
float rStep, gStep, bStep;
r = (GetRValue(m_clrEnd) - GetRValue(m_clrStart));
g = (GetGValue(m_clrEnd) - GetGValue(m_clrStart));
b = (GetBValue(m_clrEnd) - GetBValue(m_clrStart));
int nSteps = max(abs(r), max(abs(g), abs(b)));
fStep = (float)rectClient.right / (float)nSteps;
//计算每个颜色的步长
rStep = r/(float)nSteps;
gStep = g/(float)nSteps;
bStep = b/(float)nSteps;
r = GetRValue(m_clrStart);
g = GetGValue(m_clrStart);
b = GetBValue(m_clrStart);
#if 0 //modify zp 20170213 使用图片填充进度条
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP_prg);
CBrush brushQueen(&bitmap);
memDC->FillRect(&rectFill,&brushQueen);//画进度条区域
#else
// 开始填充颜色
for (int iOnBand = 0; iOnBand < nSteps; iOnBand++)
{
::SetRect(&rectFill,
(int)(iOnBand * fStep),
0,
(int)((iOnBand+1) * fStep),
rectClient.bottom+1);
VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));
memDC.FillRect(&rectFill,&brush);
VERIFY(brush.DeleteObject());
if (rectFill.right > nMaxWidth)
{
::SetRect(&rectFill, rectFill.right, 0, rectClient.right, rectClient.bottom);
VERIFY(brush.CreateSolidBrush(RGB(255,255,255)));
memDC.FillRect(&rectFill, &brush);
VERIFY(brush.DeleteObject());
return;
}
}
#endif
}
BOOL CGradientProgressCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}