2.10 进度条控件典型实例

进度条控件(Progress)用于显示程序的进度,在进行程序安装、文件传输时经常用到。

实例080 进度条百分比显示

这是一个可以提高基础技能的实例

实例位置:光盘\mingrisoft\02\080

实例说明

在设计应用程序时,通常使用进度条来描述当前的操作进度。但是MFC提供的进度条控件不能够利用精确的数字或百分比来描述进度。这要怎么解决呢?本实例实现了进度条百分比显示的功能,运行结果如图2.47所示。

技术要点

图2.47 进度条百分比显示

在进度条控件中显示文字比较简单,只需要在进度条控件的OnPaint方法中根据当前的位置值输出字符串文本就可以了。为了提供进度条窗口的绘制效率,这里使用了BeginPaint方法来获得进度条窗口的设备上下文,在进度条窗口的设备上下文使用后,调用EndPaint方法来结束进度条窗口的绘制。下面介绍这两个方法的使用。

(1)BeginPaint方法。BeginPaint方法用于为窗口准备绘制操作,将绘制的信息填充到参数中。语法如下:

HDC BeginPaint(LPPAINTSTRUCT lpPaint);

参数说明:

● lpPaint:是一个PAINTSTRUCT结构指针,表示接收的绘制信息。

返回值:表示关联窗口的设备上下文指针。

(2)EndPaint方法。EndPaint方法用于表示窗口的绘制操作结束。语法如下:

void EndPaint(LPPAINTSTRUCT lpPaint);

参数说明:

● lpPaint:是一个PAINTSTRUCT结构指针,包含了由BeginPaint方法获取的绘制信息。

实现过程

(1)新建一个基于对话框的应用程序。

(2)从CProgressCtrl类派生一个子类CTextProgress。

(3)向对话框中添加一个进度条控件,设置控件的Border和Smooth属性,关联变量m_Progress,其类型为CTextProgress。

(4)向CTextProgress类中添加成员变量。代码如下:

          COLORREF m_crText;         //文本颜色
          COLORREF m_crProgress;     //进度颜色
          COLORREF m_crBlank;        //空白区域颜色

(5)处理进度条的WM_PAINT消息,在其消息处理函数中绘制进度条的文本和当前进度。代码如下:

            void CTextProgress::OnPaint()
            {
              PAINTSTRUCT ps;
              CDC*pDC=BeginPaint(&ps);                              //开始绘制
              int nPos=GetPos();                                     //获取当前进度条的位置
              CString csPos;
              csPos.Format("%d%%",nPos);                            //格式化字符串
              CRect clientRC;
              GetClientRect(clientRC);                              //获取客户区域
              CSize sztext=pDC->GetTextExtent(csPos);                //获取字符串的高度和宽度
              int nX=(clientRC.Width()-sztext.cx)/2;                 //计算中心位置
              int nY = (clientRC.Height() - sztext.cy) / 2;
              pDC->SetBkMode(TRANSPARENT);                          //将设备上下文的背景模式设置为透明
              int nMin, nMax;
              GetRange(nMin,nMax);                                  //获取进度条的显示范围
              //获取单位刻度
              double dFraction = (double)clientRC.Width() / (nMax-nMin);
              int nLeft=nPos*dFraction;                              //计算左边距
              CRect leftRC  =clientRC;
              leftRC.right  =nLeft;
              CRect rightRC = clientRC;
              rightRC.left  =nLeft;
              pDC->FillRect(leftRC,&CBrush(m_crProgress));          //使用蓝色标识当前的进度
              pDC->FillRect(rightRC,&CBrush(m_crBlank));            //使用白色标识剩余的部分
              pDC->SetTextColor(m_crText);                          //设置文本颜色
              pDC->TextOut(nX,nY,csPos);                            //输出当前的进度
              ReleaseDC(pDC);                                       //释放设备上下文
            EndPaint(&ps);                                  //结束窗口绘制
        }

(6)处理主窗口的WM_TIMER消息,在消息处理函数中设置进度条的显示进度。代码如下:

        void CTextProgressDlg::OnTimer(UINT nIDEvent)
        {
            int nCurPos=m_Progress.GetPos();                    //获取进度条的当前位置
            m_Progress.SetPos(nCurPos+1);                      //设置进度条的位置
            CDialog::OnTimer(nIDEvent);
        }

举一反三

根据本实例,读者可以:

在滑块显示的进度条中显示进度文本。

实例081 渐变颜色的进度条

这是一个可以提高基础技能的实例

实例位置:光盘\mingrisoft\02\081

实例说明

在使用进度条时,除了用文字显示进度以外,也可以通过渐变色来显示。本实例实现了一个渐变颜色的进度条,实例运行结果如图2.48所示。

图2.48 渐变颜色的进度条

技术要点

在进度条控件中显示渐变色比较简单,只需要在进度条控件的OnPaint方法中使用循环控制颜色,然后使用FillRect填充区域就可以了。

FillRect方法用指定的画刷填充区域,语法如下:

void FillRect(LPCRECT lpRect,CBrush* pBrush);

参数说明:

● lpRect:指向RECT结构的指针,包含被填充的矩形的逻辑坐标,可以为该参数传递CRect对象。

● pBrush:标识填充矩形的画刷。

实现过程

(1)新建一个基于对话框的应用程序。

(2)从CProgressCtrl类派生一个子类CColorProgress。

(3)向对话框中添加一个进度条控件,设置控件的Border和Smooth属性,关联变量m_Progress,其类型为CColorProgress。

(4)处理进度条的WM_PAINT消息,在其消息处理函数中绘制进度条的文本和当前进度。代码如下:

        void CColorProgress::OnPaint()
        {
            PAINTSTRUCT ps;
            CDC*pDC=BeginPaint(&ps);                                //开始绘制
            int nPos=GetPos();                                       //获取当前进度条的位置
            CRect clientRC;
            GetClientRect(clientRC);                                //获取客户区域
            pDC->SetBkMode(TRANSPARENT);                            //将设备上下文的背景模式设置为透明
            int nMin, nMax;
            GetRange(nMin,nMax);                                    //获取进度条的显示范围
            //获取单位刻度
            double dFraction = (double)clientRC.Width() / (nMax-nMin);
            int nLeft=nPos*dFraction;                                //计算左边距
            CRect leftRC  =clientRC;
              leftRC.right  =nLeft;
              CRect rightRC = clientRC;
              rightRC.left  =nLeft;
              //以渐变色填充区域
              for(int m=255;m>0;m--)
              {
                  int x,y;
                  x = leftRC.Width() * m / 255;
                  pDC->FillRect(CRect(0,0,x,leftRC.Height()),&CBrush(RGB(255,m,0)));
              }
              pDC->FillRect(rightRC,&CBrush(RGB(255,255,255)));         //使用白色标识剩余的部分
              ReleaseDC(pDC);                                           //释放设备上下文
              EndPaint(&ps);                                            //结束窗口绘制
            }

(5)处理主窗口的WM_TIMER消息,在该消息的处理函数中设置进度条的显示进度。代码如下:

          void CProgressDlg::OnTimer(UINT nIDEvent)
          {
              int nCurPos=m_Progress.GetPos();                         //获取进度条的当前位置
              m_Progress.SetPos(nCurPos+1);                           //设置进度条的位置
              CDialog::OnTimer(nIDEvent);
          }

举一反三

根据本实例,读者可以:

自绘进度条控件。