#pragma once
class CGradientProgressCtrl : public CProgressCtrl
{
public:
CGradientProgressCtrl() ;
virtual ~CGradientProgressCtrl() ;
int SetPos(int nPos) ;
int SetStep(int nStep) ;
void SetRange(int nLower, int nUpper) ;
int SetText(const char * pText, BOOL bRepaint = TRUE) ;
public:
void ShowPercent(BOOL bShowPercent = TRUE) { m_bShowPercent = bShowPercent; }
void ShowText(BOOL bShowText = TRUE) { m_bShowText = bShowText; }
public:
COLORREF GetTextColor(void) { return m_clrText ; }
COLORREF GetBkColor(void) { return m_clrBkGround ; }
COLORREF GetStartColor(void) { return m_clrStart ; }
COLORREF GetEndColor(void) { return m_clrEnd ; }
void SetStartColor(COLORREF color) { m_clrStart = color ; }
void SetEndColor(COLORREF color) { m_clrEnd = color ; }
void SetTextColor(COLORREF color) { m_clrText = color ; }
void SetBkColor(COLORREF color)
{
m_clrBkGround = color ;
m_BKGroundBrush.DeleteObject();
m_BKGroundBrush.CreateSolidBrush(m_clrBkGround);
}
private:
void Draw(CPaintDC* pDC, const RECT& rectClient, const int& nMaxWidth);
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
private:
int m_nLower ;
int m_nUpper ;
int m_nStep ;
int m_nCurPos ;
COLORREF m_clrStart ;
COLORREF m_clrEnd ;
COLORREF m_clrBkGround ;
COLORREF m_clrText ;
BOOL m_bShowPercent ;
BOOL m_bShowText ;
char m_Text[32] ;
char m_Percent[4] ;
CBrush m_BKGroundBrush ;
CBrush m_TempBrush ; // 临时刷子
private:
class CMemDC : public CDC
{
public:
CMemDC(CDC* pDC):CDC()
{
ASSERT(pDC != NULL);
m_pDC = pDC;
m_pOldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();
if (m_bMemDC)
{
pDC->GetClipBox(&m_rect);
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_bitmap);
SetWindowOrg(m_rect.left, m_rect.top);
}
else
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
virtual ~CMemDC()
{
if (m_bMemDC)
{
m_pDC->BitBlt(m_rect.left,
m_rect.top,
m_rect.Width(),
m_rect.Height(),
this,
m_rect.left,
m_rect.top,
SRCCOPY
);
SelectObject(m_pOldBitmap);
}
else
{
m_hDC = m_hAttribDC = NULL;
}
}
CMemDC* operator->()
{
return this;
}
operator CMemDC*()
{
return this;
}
private:
CBitmap m_bitmap;
CBitmap* m_pOldBitmap;
CDC* m_pDC;
CRect m_rect;
BOOL m_bMemDC;
};
};
#include "stdafx.h"
#include "GradientProgressCtrl.h"
CGradientProgressCtrl::CGradientProgressCtrl()
{
m_nLower = 0 ;
m_nUpper = 100 ;
m_nCurPos = 0 ;
m_nStep = 1 ;
m_clrStart = COLORREF(RGB(255, 0, 0)) ;
m_clrEnd = COLORREF(RGB(0, 0, 255)) ;
m_clrBkGround = ::GetSysColor(COLOR_3DFACE) ;
m_clrText = COLORREF(RGB(255, 255, 255)) ;
m_bShowPercent = TRUE ;
m_bShowText = TRUE ;
m_BKGroundBrush.CreateSolidBrush(m_clrBkGround) ;
memset(m_Text, 0, 32);
}
CGradientProgressCtrl::~CGradientProgressCtrl()
{
m_BKGroundBrush.DeleteObject();
}
BEGIN_MESSAGE_MAP(CGradientProgressCtrl, CProgressCtrl)
ON_WM_PAINT()
END_MESSAGE_MAP()
void CGradientProgressCtrl::SetRange(int nLower, int nUpper)
{
m_nLower = nLower ;
m_nUpper = nUpper ;
m_nCurPos = nLower ;
CProgressCtrl::SetRange(nLower, nUpper);
CProgressCtrl::SetPos(nLower);
}
int CGradientProgressCtrl::SetStep(int nStep)
{
m_nStep = nStep;
return (CProgressCtrl::SetStep(nStep));
}
int CGradientProgressCtrl::SetPos(int nPos)
{
m_nCurPos = nPos;
return (CProgressCtrl::SetPos(nPos));
}
int CGradientProgressCtrl::SetText(const char * pText, BOOL bRepaint)
{
strcpy(m_Text, pText);
if (bRepaint && m_bShowText)
{
Invalidate(TRUE);
}
return 0;
}
void CGradientProgressCtrl::OnPaint()
{
CPaintDC dc(this);
RECT rectClient;
GetClientRect(&rectClient);
if (m_nCurPos <= m_nLower || m_nCurPos > m_nUpper)
{
dc.FillRect(&rectClient, &m_BKGroundBrush);
return;
}
float maxWidth((float) m_nCurPos /(float) m_nUpper*(float) rectClient.right);
Draw(&dc, rectClient, (int) maxWidth);
dc.SetTextColor(m_clrText);
dc.SetBkMode(TRANSPARENT);
HGDIOBJ hOldFont = ::SelectObject(dc.m_hDC, ::GetStockObject(DEFAULT_GUI_FONT));
if (m_bShowPercent)
{
sprintf(m_Percent, "%d%% ",(int) (100 * (float) m_nCurPos / m_nUpper));
dc.DrawText(m_Percent, &rectClient, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
}
if (m_bShowText)
{
rectClient.left = (rectClient.left + rectClient.right) / 2;
dc.DrawText(m_Text, &rectClient, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
}
::SelectObject(dc.m_hDC, hOldFont);
}
void CGradientProgressCtrl::Draw(CPaintDC* pDC, const RECT& rectClient, const int& nMaxWidth)
{
RECT rectFill;
float fStep;
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);
for (int iOnBand = 0; iOnBand < nSteps; iOnBand++)
{
::SetRect(&rectFill, (int) (iOnBand * fStep), 0,
(int) ((iOnBand + 1) * fStep), rectClient.bottom + 1);
VERIFY(m_TempBrush.CreateSolidBrush(RGB(r + rStep * iOnBand,
g + gStep * iOnBand,
b + bStep * iOnBand)));
memDC.FillRect(&rectFill, &m_TempBrush);
VERIFY(m_TempBrush.DeleteObject());
if (rectFill.right > nMaxWidth)
{
::SetRect(&rectFill, rectFill.right, 0, rectClient.right,
rectClient.bottom);
VERIFY(m_TempBrush.CreateSolidBrush(m_clrBkGround));
memDC.FillRect(&rectFill, &m_TempBrush);
VERIFY(m_TempBrush.DeleteObject());
return;
}
}
}