我在做一个文件下载程序时,需要定制一个进度条(类似于迅雷)。
具体需求:
1. 支持文本显示。2. 文本以小数表示。
3. 文本被进度条覆盖时,覆盖部分显示一种颜色,未覆盖部分显示另一种颜色。
处理方法:
需求1、默认进度条不包含显示文本。文本需要在OnPaint函数里手动绘制。需求2、默认进度条以整数表示进度。SetRange、SetStep、SetPos、OffsetPos等进度条设置函数,需要改写成浮点数版本。
需求3、文本显示区域存在颜色变化。不同颜色的文本可以通过剪裁区域来控制绘制。
部分源码:
void CProgressCtrlEx::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
// 设置自绘
ModifyStyle(0, BS_OWNERDRAW) ;
// 去掉边界
ModifyStyleEx(WS_EX_STATICEDGE, 0);
CProgressCtrl::PreSubclassWindow();
}
BOOL CProgressCtrlEx::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CProgressCtrlEx::OnPaint()
{
CPaintDC dc(this);
if (m_fLower > m_fUpper)
{
return;
}
// 整个客户区
CRect rcClient;
GetClientRect(&rcClient);
// 框内客户区
CRect rcInner(rcClient);
rcInner.DeflateRect(1, 1, 1, 1);
float fRatio;
fRatio = (float)(m_fPos - m_fLower) / ((float)(m_fUpper - m_fLower));
float fRcWidth, fRcHeigth;
fRcWidth = (float)rcInner.Width() * fRatio;
fRcHeigth = (float)rcInner.Height();
CRect rcLeftRect, rcRightRect;
rcLeftRect = rcRightRect = rcInner;
rcLeftRect.right = rcLeftRect.left + (int)fRcWidth;
rcRightRect.left = rcLeftRect.right;
// 创建缓冲
CDC dcMem1st;
dcMem1st.CreateCompatibleDC(&dc);
CDC dcMem2nd;
dcMem2nd.CreateCompatibleDC(&dc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
CBitmap *pOldBmp = dcMem1st.SelectObject(&bmp);
// 绘制边框
CPen pen;
pen.CreatePen(PS_SOLID, 1, m_clrEgColor);
CPen *pOldPen = dcMem1st.SelectObject(&pen);
dcMem1st.MoveTo(rcClient.TopLeft());
dcMem1st.LineTo(rcClient.right-1, rcClient.top);
dcMem1st.LineTo(rcClient.right-1, rcClient.bottom-1);
dcMem1st.LineTo(rcClient.left, rcClient.bottom-1);
dcMem1st.LineTo(rcClient.TopLeft());
// 绘制背景
dcMem1st.FillSolidRect(rcInner.left, rcInner.top, rcInner.Width(), rcInner.Height(), m_clrBkColor);
// 绘制前景
if (m_hBmpBk != NULL)
{
HBITMAP hOldBmp2nd = (HBITMAP)dcMem2nd.SelectObject(m_hBmpBk);
dcMem1st.StretchBlt(
rcInner.left, rcInner.top,
(int)fRcWidth, (int)fRcHeigth,
&dcMem2nd,
0, 0,
(int)m_fBmpBkWidth, (int)m_fBmpBkHeight,
SRCCOPY
);
dcMem2nd.SelectObject(hOldBmp2nd);
}
else
{
dcMem1st.FillSolidRect(
rcInner.left, rcInner.top,
(int)fRcWidth, (int)fRcHeigth,
m_clrForeColor
);
}
// 绘制文本
if (m_bShowText)
{
CString strRadio;
strRadio.Format(_T("%.1f%%"), fRatio * 100.0f);
CRgn rgnTx;
// 绘制左文本
rgnTx.CreateRectRgn(rcLeftRect.left, rcLeftRect.top, rcLeftRect.right, rcLeftRect.bottom);
dcMem1st.SelectClipRgn(&rgnTx);
dcMem1st.SetTextColor(m_clrTextNewColor);
dcMem1st.SetBkMode(TRANSPARENT);
dcMem1st.DrawText(strRadio, rcInner, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
rgnTx.DeleteObject();
// 绘制右文本
rgnTx.CreateRectRgn(rcRightRect.left, rcRightRect.top, rcRightRect.right, rcRightRect.bottom);
dcMem1st.SelectClipRgn(&rgnTx);
dcMem1st.SetTextColor(m_clrTextOldColor);
dcMem1st.DrawText(strRadio, rcInner, DT_CENTER | DT_VCENTER | DT_VCENTER | DT_SINGLELINE);
rgnTx.DeleteObject();
}
dc.BitBlt(
0, 0,
rcClient.Width(), rcClient.Height(),
&dcMem1st,
0, 0,
SRCCOPY
);
// 回收资源
dcMem1st.SelectObject(pOldBmp);
dcMem1st.SelectObject(pOldPen);
dcMem1st.DeleteDC();
dcMem2nd.DeleteDC();
pen.DeleteObject();
bmp.DeleteObject();
}
void CProgressCtrlEx::SetRange(float fLower, float fUpper)
{
m_fLower = fLower;
m_fUpper = fUpper;
}
float CProgressCtrlEx::GetStep()
{
return m_fStep;
}
float CProgressCtrlEx::SetStep(float fStep)
{
float fOldStep;
fOldStep = m_fStep;
m_fStep = fStep;
return fOldStep;
}
float CProgressCtrlEx::GetPos()
{
return m_fPos;
}
float CProgressCtrlEx::SetPos(float fPos)
{
if (!::IsWindow(m_hWnd))
{
return -1;
}
float fOldPos;
fOldPos = m_fPos;
m_fPos = fPos;
if (fOldPos < m_fPos)
{
RedrawWindow();
}
return m_fPos;
}
float CProgressCtrlEx::StepIt()
{
return SetPos(m_fPos + m_fStep);
}
float CProgressCtrlEx::OffsetPos(float fPos)
{
return SetPos(m_fPos + fPos);
}
运行效果图:
完整源码地址:http://download.csdn.net/detail/zwz1984/4867448