重绘进度条控件

计算机在处理耗时任务时,常以进度条实时的显示处理速度,完成量等信息。

我在做一个文件下载程序时,需要定制一个进度条(类似于迅雷)。

具体需求:

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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值