当窗口尺寸发生变化时,窗口会发生一个重绘,于是会发生一个WM_PAINT消息,为CMainFrame类添加WM_PAINT消息的响应函数OnPaint,而且当窗口第一次显示时,就会调用OnPaint函数。
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect rect(1,2,3,4);
m_wndStatusBar.GetItemRect(1,&rect);
m_progress.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,123);
m_progress.SetPos(50);
// Do not call CFrameWnd::OnPaint() for painting messages
}
但是运行后改变窗口的大小时,发生了错误:。我们曾经在第七章中也发生过类似的错误,在本例中主要是因为在OnCreate函数中,程序已经创建了一个进度栏,并与m_progress对象相关联。然后改变窗口大小后,程序调用OnPaint函数,函数体中又创建了一个进度栏,并妄想与m_progress相关联,于是发生了错误。既然已经存在了进度栏,我们就可以在把进度栏移动到目标矩形区域中,而不是再次创建。首先,我们需要判断m_progress对象是否已经绑定了一个进度栏。我们可以通过判断m_progress对象的窗口句柄是否为空,即NULL。而移动一个窗口,可以调用CWnd::MoveWindow来实现。因此修改后的OnPaint函数代码:
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect rect(1,2,3,4);
m_wndStatusBar.GetItemRect(1,&rect);
if(!m_progress.m_hWnd)
m_progress.Create(WS_CHILD|WS_VISIBLE,rect,&m_wndStatusBar,123);
else
m_progress.MoveWindow(rect);
m_progress.SetPos(50);
// Do not call CFrameWnd::OnPaint() for painting messages
}
(本例中还可以使用SetWindowPos函数设置进度栏的位置)
利用CProgressCtrl类的StepIt成员函数可以实现进度栏上以某种现实方式不断增加当前位置。而步长的设置可以通过CProgressCtrl::SetStep,而CProgressCtrl::SetRange函数可以设置进度栏的范围,默认范围是0-100.
让我们回到Style程序,让进度栏的当前位置每隔一秒钟就前进一步,也就是在CMainFrame类中的OnTimer函数中添加所示灰色代码:
void CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CTime t=CTime::GetCurrentTime();
CString str=t.Format("%H:%M:%S");
CClientDC dc(this);
CSize sz=dc.GetTextExtent(str);
m_wndStatusBar.SetPaneText(1,str);
m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx);
m_progress.StepIt();
CFrameWnd::OnTimer(nIDEvent);
}
如果想让进度栏平滑得动起来,就为进度栏设置PBS_SMOOTH类型。