6.14--如何在状态栏内显示一个进度指示器?

      使用EkCreateProgressBar()函数,可容易的实现在一个 MFC应用程序 的 状态栏内显示一个进度指示器。


BOOL EkCreateProgressBar( CProgressCtrl* pProgressCtrl,
                                              CStatusBar* pStatusBar,
                                              LPCTSTR szMessage = NULL,
                                              int nPaneIndex = 0,
                                              int cxMargin = 10,
                                              int cxMaxWidth = -1,
                                              UINT nIDControl = 1 )
{
       ASSERT_VALID( pProgressCtrl );
       ASSERT_VALID( pStatusBar );

      // 1 - 为进度条控件计算目标矩形
      CRect rc;
      pStatusBar->GetItemRect( nPaneIndex, &rc );

 

      // 2 - 定义进度条的水平偏移
      if( szMessage != NULL )
      {
            // 计算消息文本宽度

            CClientDC dc( pStatusBar );
            CFont* pFont = pStatusBar->GetFont();
            CFont* pOldFont = dc.SelectObject( pFont );
            CSize sizeText = dc.GetTextExtent( szMessage );
            dc.SelectObject( pOldFont );

            rc.left += sizeText.cx + cxMargin;
      }

 

      // 3 - 计算进度条宽度
      if( cxMaxWidth != -1 )
      {
            rc.right = rc.left + min( cxMaxWidth, rc.Width() );
      }

      // 4 - 显示消息文本
      pStatusBar->SetPaneText( nPaneIndex, szMessage );
      pStatusBar->RedrawWindow();

      // 5 - 创建进度条控件
      return pProgressCtrl->Create( WS_CHILD | WS_VISIBLE,rc, pStatusBar, nIDControl );
}

该函数的参数说明:

@pProgressCtrl定义了与即将创建的进度条控件相关联的C++对象。该c++对象的生命周期在EkCreateProgressBar()调用函数内,通常,该C++对象分配在堆栈上,参加下面的示例代码。

@pStatusBar是状态栏指针,在其上将创建进度条控件

@szMessage是指向 显示在 进度条控件左边 的状态栏内 的字符串,默认值NULL,不显示任何消息

@nPaneIndex是基于0的 状态栏格 索引,在基于索引的状态栏格上创建 进度条

@cxMargin是szMessage文本结束处 和 进程控件左端 之间的距离(以像素计算)。默认值是10个像素点。

@cxMaxWidth是进度条控件最大的宽度(以像素计算),默认值-1导致进度条控件展开,从而占有所有剩余的格的宽度

@nIDControl是将要创建的Windows进度条控件的子窗口ID。在大多数情况下,无需考虑这个ID

 

      一般,使用EkCreateProgressBar()在状态栏上创建一个进度条控件,步骤如下:

(1)定义一个c++ CProgressCtrl对象

(2)使用EkCreateProgressBar()来创建进度条

(3)初始化进度条控件的范围和步长尺寸

(4)通过调用CProgressCtrl::StepIt()或CProgressCtrl::StepPos(),来执行长任务,并周期性的更新进度条控件

(5)随意的在CProgressCtrl对象上调用DestroyWindow()来隐藏并销毁进度条控件

 

下面的代码说明了上面的步骤和该函数的用法:

void CMainFrame::OnDemoLongTask1()
{
      //1、定义一个c++ CProgressCtrl对象
      CProgressCtrl wndProgress;
      //2、使用EkCreateProgressBar()来创建进度条
      EkCreateProgressBar(&wndProgress, &m_wndStatusBar,_T( "Executing a long task (1), press Esc to cancel..." ) );
    
      //3- 初始化进度条控件的范围和步长尺寸
     wndProgress.SetRange( 0, 100 );
     wndProgress.SetStep( 1 );

 

     //4- 这里就是执行长任务,并定期调用wndProgress.StepIt()来更新进度条控件的地方
     //对于这里的演示,用了一个For循环和sleep()函数来仿真该长任务。
    srand( (unsigned)time( NULL ) );//获得当前的时间 作为 随机数的种子
    for( int i = 0; i < 100; ++i )
    {
          // 4 - 测试ESC键
          short t=::GetAsyncKeyState( VK_ESCAPE );

            if( ::GetAsyncKeyState( VK_ESCAPE ) < 0 )
            {
                  break;
            }

 

           //MulDiv(a,b,c)就是计算a*b/c,不过在a*b>2^32仍保证结果正确
           int nSleepTime = MulDiv( 100, rand(), RAND_MAX );
           Sleep( nSleepTime );

 

          // 5 - 更新进度条控件
          wndProgress.StepIt();
    }

 

       // 6 - 确定空闲消息再次被显示(即默认在状态栏的左端显示“就绪”,如果进度条左端有文字提示,显示完进度条后,发送该消息确保左端再次显示“就绪”),对于WM_SETMESSAGESTRING消息,需要包含头文件“#include<afxpriv.h>”
       PostMessage( WM_SETMESSAGESTRING, (WPARAM) AFX_IDS_IDLEMESSAGE, 0L );
}


函数原型:SHORT GetAyncKeystateint vKey);
    
参数
    vKey:
定义虚拟键码(若有256个虚拟键码)。欲获得更多信息,参看Virtual_Key Codes。在Windows NT中可以使用左右键区分常量来定义某些键。欲获得更多信息,参看备注部分。
    
返回值:

      若函数调用成功,返回值给出了自最后一次调用GetAsyncKeyStat。以来,指定的键是否处于按下状态,并且确定了该键目前是按下或是被弹起。若最高位被置为1,则键被接下若最低位被置为1,则该键在前次调用GetAsyncKeystate以来处于被接下的状态。若另一进程或线程中的窗口拥有键盘焦点,则返回值为零。

    Windows 95
Windows 95不支持左右键区分常量,若用这些常量调用GetAsyncKeystate函数,则返回值为零。

    
备注:该函数支持鼠标按钮,但是,它检查的不是物理按钮映射到的逻辑按钮的状态,而实际物理按钮的状态。例如,函数调用GetAsyncKeystateVK_LBUTTON)总是返回物理的鼠标左按钮的状态,而不管该按钮映射为逻辑上的左按钮,可以调用GetsystemMetricsSM_SWAPBUTON)来确定系统当前物理鼠标按钮与逻辑鼠标按钮的对应关系,当鼠标按钮被左右交换后,函数返回TRUE

    
可以使用虚拟键码常数VD_SHIFTVK_CONTROLVK_MENU作为vKey参数的值,这样给出Shift CtrlAIt键的状态,而不区分是左键还是右键。
    Windows NT
:可以使用如下的虚拟键码常数作为vKey的值来区分左右键的情况:
    VK_LSHIFT VK_RSHIFT;VW_LCONTROL VK_RCONTROL
VK_LMENU VK_RMENU
    
这些可区分的左右键常量仅当调用GetKeyboardStateSetKeyboardstateGetAsyncKeyStateGetKeyStateMaPViruaIKey函数时才可用。

 

 

 

 


关于srand()、time()、rand()几个函数的说明:

srand(设置随机数种子)
         头文件
         #include<stdlib.h>

         函数定义
         void srand (unsigned int seed);

         函数说明
         srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,通常可以利用geypid()或time(0)的返回值来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。

         示例代码
         #include<time.h>
         #include<stdlib.h>
         main()
         {
               int i,j;
               srand((int)time(0));
               for(i=0;i<10;i++)
              {
                     j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
                     printf(" %d ",j);
              }
         }

         执行
         5 8 8 8 10 2 10 8 9 9
         2 9 7 4 10 3 2 10 8 7

rand()

         表头文件
         #include<stdlib.h>

         定义函数
         int rand(void)

         函数说明
         rand()会返回一随机数值,范围在0至RAND_MAX 间。在调用此函数产生随机数前,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。

         返回值
         返回0至RAND_MAX之间的随机数值,RAND_MAX定义在stdlib.h,其值为2147483647。

         示例代码:

         #include<stdlib.h>
         main()
         {
               int i,j;
               for(i=0;i<10;i++)
              {
                     j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
                     printf("%d ",j);
              }
         }

         执行
         9 4 8 8 10 2 4 8 3 6
         9 4 8 8 10 2 4 8 3 6

1、rand返回0-RAND_MAX之间均匀分布的伪随机整数。 RAND_MAX必须至少为32767。rand()函数不接受参数,默认以1为种子(即起始值)。随机数生成器总是以相同的种子开始,所以形成的伪随机数列也相同,失去了随机意义。(但这样便于程序调试)
2、C++中另一函数srand(),可以指定不同的数(无符号整数变元)为种子。但是如果种子相同,伪随机数列也相同。一个办法是让用户输入种子,但是仍然不理想。
3、 比较理想的是用变化的数,比如时间来作为随机数生成器的种子。 time的值每时每刻都不同。所以种子不同,所以,产生的随机数也不同。
// C++随机函数(VC program)
#include <stdlib.h>
#include <iostream>
#include <time.h>
using namespace std;
#define MAX 100
int main(int argc, char* argv[])
{
     srand( (unsigned)time( NULL ) );//srand()函数产生一个以当前时间开始的随机种子
     for (int i=0;i<10;i++)
           cout<<rand()%MAX<<endl;//MAX为最大值,其随机域为0~MAX-1
     return 0;
}


 

产生某一范围内的随机数:

     rand()%d,一个0~d-1的随机数



 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值