创建进度对话框的简易指南

在软件开发中,创建一个进度对话框可能是一个挑战。尽管可以重用现有的对话框,但它可能看起来不是想要的样子,或者很难集成到代码中。幸运的是,IE 5为提供了一个解决方案,不需要再构建对话框或编写处理取消按钮的代码了!

BROWSEUI.DLL文件实现了一个名为IProgressDialog的COM接口,它提供了一个看起来像资源管理器和SHFileOperation()显示的对话框。

进度对话框的特点

进度对话框具有以下特点:

AVI文件应该是272x60大小,并受到动画公共控件的常规限制。如果没有自己的AVI文件,MSVC附带了一些示例文件(在CD上的\common\graphics\avis目录中),或者可以打开shell32.dll的资源编辑器并从中获取一个。(如果想知道,在上面的屏幕截图中从Internet FastFind获取了AVI。)

尽管文档指出可以从对话框中移除最小化按钮,但这似乎在Windows 2000的2195版本中也是有问题的。对话框将始终有一个最小化按钮(至少在微软修复它之前)。

MFC封装类CSHProgressWnd

由于COM方法有几个标志和保留参数,编写了一个薄薄的MFC包装类CSHProgressWnd,这使得代码更加易读。MFC类不是从CWnd派生的,因为COM接口不直接提供对进度窗口的访问。这意味着甚至可以在控制台应用程序或其他不使用CWnd框架的情况下使用包装器。

如果在想名字,在类名中加入了"SH",因为MSDN指出IProgressDialog接口实际上是shell32.dll的一部分(并且只在Windows 2000上可用!),使用"SH"来表示它是一个shell特性。后来发现对话框在旧版本的Windows上也能很好地工作,但那时已经完成了代码。

CSHProgressWnd构造函数创建一个IProgressDialog对象。在一个正常工作的系统上,这总是会成功的。然而,如果想再次检查一切是否正常工作,可以调用IsValid()函数。注意,必须在使用CSHProgressWnd对象之前初始化OLE(例如,使用AfxOleInit())。

CSHProgressWnd析构函数销毁对话框并释放COM接口

调用这些函数来确定对话框的外观。

void SetTitle ( LPCTSTR szTitle )

设置进度对话框标题栏中显示的文本。

void SetAnimation ( HINSTANCE hinst, UINT uRsrcID ) void SetAnimation ( UINT uRsrcID )

指定一个包含将在对话框中显示的AVI的资源。第一个函数接受包含资源的模块的HINSTANCE。第二个形式使用AfxGetResourceHandle()的返回值作为模块。

void SetCancelMessage ( LPCTSTR szMessage )

设置用户点击取消按钮时在第三行显示的文本。

void SetCalculateTime ( bool bCalculate = true )

设置进度对话框是否在第三行显示剩余时间的估计。如果不调用SetCalculateTime(),对话框默认显示剩余时间。

void SetAllowMinimize ( bool bAllow = true )

设置进度对话框是否包含最小化按钮。如果不调用SetAllowMinimize(),对话框默认包含一个最小化按钮。注意:调用SetAllowMinimize(false)不会移除最小化按钮;这似乎是对话框实现中的一个错误。

void SetShowProgressBar ( bool bShow = true )

设置进度对话框是否显示进度条。如果不调用SetShowProgressBar(),对话框默认包含一个进度条。

进度对话框可以是模态的或非模态的。调用这两个函数中的一个来显示对话框。

HRESULT ShowModal ( CWnd* pwndParent )

将对话框作为模态对话框显示。pwndParent是指向父窗口的指针。使用SUCCEEDED()宏测试返回值以确定对话框是否成功创建。如果对话框未创建,返回值是IProgressDialog::StartProgressDialog()方法返回的错误。

HRESULT ShowModeless ( CWnd* pwndParent )

与ShowModal()相同,但进度对话框是非模态的而不是模态的。

void SetLineText ( DWORD dwLine, LPCTSTR szText, bool bCompactPath = false )

设置对话框中的三行文本之一。dwLine可以是1、2或3。第1行和第2行出现在AVI和进度条之间,第3行出现在进度条下方。如果让对话框计算剩余时间(通过调用SetCalculateTime(true)),对话框使用第3行显示估计的剩余时间,并且该行对SetLineText()不可用。如果正在显示文件名或路径,请为第三个参数传递true,以便对话框缩短路径以适应对话框。

void UpdateProgress ( DWORD dwProgress, DWORD dwMax ) void UpdateProgress ( DWORD dwProgress )

UpdateProgress()设置对话框的进度指示器。第一个函数形式设置当前和最大进度值。这些可以是,例如,0和100,但确切的值由决定。必须第一次调用第一个形式,然后只要最大进度值不变,就可以调用第二个形式。如果需要,可以自由地改变最大值,只要在最大值变化时调用第一个形式。

void UpdateProgress ( ULONGLONG u64Progress, ULONGLONG u64ProgressMax ) void UpdateProgress ( ULONGLONG u64Progress )

这两个函数的工作方式与前两个相同,只是它们接受64位数字而不是DWORD。

bool HasUserCanceled()

应该定期调用HasUserCanceled(),如果函数返回true,则退出。

void EndDialog()

调用EndDialog()关闭进度对话框。CSHProgressWnd析构函数也会在对话框仍然可见时关闭对话框。

void ResetTimer() void CMyDialog::ProcessSomeStuff() { CSHProgressWnd dlg; const DWORD dwMax = 100; TCHAR szMsg[256]; dlg.SetTitle ( _T("Hang on a sec...") ); dlg.SetAnimation ( IDR_PROGRESS_AVI ); dlg.SetCancelMessage ( _T("Cancelling this operation...") ); dlg.SetLineText ( 1, _T("Unzipping files...") ); if ( FAILED( dlg.ShowModal ( this ) ) ) return; dlg.UpdateProgress ( 0, dwMax ); for ( DWORD dwProgress = 0; dwProgress < dwMax && !dlg.HasUserCanceled(); dwProgress += 5 ) { DoSomeSlowProcessing(); wsprintf ( szMsg, _T("I'm %lu%% done"), dwProgress ); dlg.SetLineText ( 2, szMsg ); dlg.UpdateProgress ( dwProgress ); } dlg.EndDialog(); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485