使用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 GetAyncKeystate(int vKey);
参数:
vKey:定义虚拟键码(若有256个虚拟键码)。欲获得更多信息,参看Virtual_Key Codes。在Windows NT中可以使用左右键区分常量来定义某些键。欲获得更多信息,参看备注部分。
返回值:
若函数调用成功,返回值给出了自最后一次调用GetAsyncKeyStat。以来,指定的键是否处于按下状态,并且确定了该键目前是按下或是被弹起。若最高位被置为1,则键被接下:若最低位被置为1,则该键在前次调用GetAsyncKeystate以来处于被接下的状态。若另一进程或线程中的窗口拥有键盘焦点,则返回值为零。
Windows 95:Windows 95不支持左右键区分常量,若用这些常量调用GetAsyncKeystate函数,则返回值为零。
备注:该函数支持鼠标按钮,但是,它检查的不是物理按钮映射到的逻辑按钮的状态,而实际物理按钮的状态。例如,函数调用GetAsyncKeystate(VK_LBUTTON)总是返回物理的鼠标左按钮的状态,而不管该按钮映射为逻辑上的左按钮,可以调用GetsystemMetrics(SM_SWAPBUTON)来确定系统当前物理鼠标按钮与逻辑鼠标按钮的对应关系,当鼠标按钮被左右交换后,函数返回TRUE。
可以使用虚拟键码常数VD_SHIFT,VK_CONTROL,VK_MENU作为vKey参数的值,这样给出Shift Ctrl,AIt键的状态,而不区分是左键还是右键。
Windows NT:可以使用如下的虚拟键码常数作为vKey的值来区分左右键的情况:
VK_LSHIFT VK_RSHIFT;VW_LCONTROL VK_RCONTROL;VK_LMENU VK_RMENU
这些可区分的左右键常量仅当调用GetKeyboardState,SetKeyboardstate,GetAsyncKeyState,GetKeyState和MaPViruaIKey函数时才可用。
关于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的随机数