65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 IE 5 内置进度对话框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (8投票s)

2000年2月7日

viewsIcon

215719

downloadIcon

1826

IE 5 提供的进度对话框的包装类。

  • 下载示例项目 - 20K
  • 进度对话框

    这是我们都讨厌的枯燥任务之一:编写一个进度对话框。它与键入“ListView_SetExtendedListViewStyleEx”一样令人头疼。即使你能重用现有的对话框,它可能也不会完全是你想要的样式,或者可能很难集成到你的代码中。

    幸运的是,IE 5 使我们再也不用自己构建对话框或编写代码来处理“取消”按钮了!BROWSEUI.DLL 文件实现了一个名为 IProgressDialog 的 COM 接口,该接口提供了一个看起来像 Explorer 和 SHFileOperation() 显示的对话框。

    进度对话框具有以下特点

     [Dialog screen shot - 22K]

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

    尽管文档声明您可以从对话框中移除最小化按钮,但这似乎不起作用,即使在 Windows 2000 的 build 2195 中也是如此。对话框将*始终*有一个最小化按钮(目前是这样,直到 Microsoft 修复它)。

    由于 COM 方法有多个标志和保留参数,我编写了一个精简的 MFC 包装类 CSHProgressWnd,它使您的代码更具可读性。MFC 类不派生自 CWnd,因为 COM 接口不直接提供对进度窗口的访问。这意味着您可以在控制台应用程序或其他不使用 CWnd 框架的情况中使用此包装器。我并不怎么使用 MFC(我最常使用的是内存验证例程,如 AfxIsValidString()),因此如果您愿意,可以非常轻松地移除对 MFC 的依赖。

    如果您想知道这个名字的由来,我在类名中加上了“SH”,因为 MSDN 指出 IProgressDialog 接口实际上是 shell32.dll 的一部分(并且仅在 Windows 2000 上可用!),我用“SH”来表示这是一个 Shell 功能。我后来发现这个对话框在旧版本的 Windows 上也能正常工作,但那时我已经完成了代码。

    CSHProgressWnd 函数

    构造/析构

    CSHProgressWnd 构造函数创建一个 IProgressDialog 对象。在正常工作的系统上,这始终会成功。但是,您可以调用 IsValid() 函数以再次检查一切是否正常。请注意,您必须先初始化 OLE(例如使用 AfxOleInit()),然后才能构造 CSHProgressWnd 对象。

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

    对话框设置

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

    void SetTitle ( LPCTSTR szTitle )
    设置显示在进度对话框标题栏中的文本。

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

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

    void SetCancelMessage ( LPCTSTR szMessage )
    设置当用户单击“取消”按钮时,在第 3 行显示的文本。

    void SetCalculateTime ( bool bCalculate = true )
    设置进度对话框是否显示剩余时间的估计值。如果您不调用 SetCalculateTime(),对话框将默认显示剩余时间。

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

    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()
    如果您想重置对话框用于估计剩余时间的计时器,请在处理循环的开始处调用 ResetTimer()。对话框使用 ResetTimer()UpdateProgress() 调用之间的时间来计算剩余时间。通常您不需要调用此函数;如果您不调用它,对话框将根据对话框创建(通过 ShowModal()ShowModeless())到第一次调用 UpdateProgress() 之间经过的时间来估算。

    使用 CSHProgressWnd 的示例代码

    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();
    }

    您可以在 http://home.inreach.com/mdunn/code/ 获取此文章和其他文章的更新。

    © . All rights reserved.