一,问题起因
进度条的使用是因为大量的计算非常耗时间,而又不可能让用户在那里傻等,因为就出现了进度条,告诉用户当前过程已经进行到了哪一步,这样就可以给用户一个很直观的表现。但是,不是所有的耗时间的计算过程都是可以量化的,比如一个计算工作总量不知道,我们就算知道每一次它进行了多少,也是没办法实时绘制滚动条的,特别明显的一个应用场景在excel插件中,数据的请求,单元格的填充,这些进度都是无法估量的,因此就出现了来回滚动效果的进度条。
二,效果图
就截了一张静态图,整个效果就是蓝色滑块在来回的滚动
三,解决方案
实现方案很简单,相信一看到标题,很多聪明的小伙伴就知道该怎么做了。没错,主要的实现机制就是一个定时器,然后在定时响应中重新计算滑块的位置,触发重绘。
四,代码
截图部分代码如下,完整代码请下载源码
对外的两个接口用于开启滚动和停止滚动。
void CProgressCtrlEx::MarqueeStart()
{
m_bRun = TRUE;
SetTimer(m_nIDEvent, m_nTime, NULL);
}
void CProgressCtrlEx::MarqueeStop()
{
m_bRun = FALSE;
KillTimer(m_nIDEvent);
}
定时器中主要是做一个滑块位置的重计算,然后Invalidate()重绘。再在OnPaint中进行绘制即可。
LRESULT CProgressCtrlEx::DoMarqueeBounce(WPARAM wParam, LPARAM lParam)
{
CRect newprog = m_borderbox;
newprog.DeflateRect(2, 2, 2, 2);
int progWidth = m_progressBitmap->GetWidth();
if (m_bMarqueeForward)
{
m_nMarqueeX += m_nMarqueeStep;
}
else
{
m_nMarqueeX -= m_nMarqueeStep;
}
newprog.left += m_nMarqueeX;
newprog.right = newprog.left + progWidth;
int leftBoundry = m_backbox.left + 1;
int rightBoundry = m_backbox.right - 1;
if (m_nMarqueeX <= leftBoundry)
{
m_bMarqueeForward = TRUE;
}
else if (m_nMarqueeX + newprog.Width() >= rightBoundry)
{
m_bMarqueeForward = FALSE;
}
newprog.top += 1;
newprog.bottom += 1;
m_progressbox = newprog;
Invalidate();
return 0;
}