Click here to Skip to main content
12,074,763 members (57,519 online)
Click here to Skip to main content
Add your own
alternative version


60 bookmarked

Using the IE 5 built-in progress dialog

, 6 Feb 2000
Rate this:
Please Sign up or sign in to vote.
A wrapper class for the progress dialog provided by IE 5.
<!-- Article Starts -->
  • Download sample project - 20K
  • The progress dialog

    It's one of those boring tasks we all hate to do: writing a progress dialog. It ranks right up there with typing "ListView_SetExtendedListViewStyleEx". And even if you're able to reuse an existing dialog, it might not look just the way you want it to, or it might be tough to integrate into your code.

    Fortunately, IE 5 saves us from having to build a dialog or write code to handle a Cancel button ever again! The BROWSEUI.DLL file implements a COM interface called IProgressDialog that provides a dialog that looks like the one displayed by Explorer and SHFileOperation().

    The progress dialog has these features:

     [Dialog screen shot - 22K]

    The AVI file should be 272x60 and is subject to the normal restrictions of the animation common control. If you don't have an AVI of your own, MSVC comes with some sample ones (in the \common\graphics\avis directory on the CD), or you can open up shell32.dll in the resource editor and swipe one from there. (If you were wondering, I snagged the AVI in the screen shot above from Internet FastFind.)

    Even though the documentation states that you can remove the minimize button from the dialog, this appears to be broken, even in build 2195 of Windows 2000. The dialog will always have a minimize button (for the time being, until Microsoft fixes it).

    Since the COM methods have several flags and reserved parameters, I wrote a thin MFC wrapper class, CSHProgressWnd, that makes your code much more readable. The MFC class is not derived from CWnd since the COM interface doesn't provide access to the progress window directly. That means you can use the wrapper even in console apps or other situations where you don't use the CWnd framework. I don't use much MFC stuff (the features I use most are memory validation routines like AfxIsValidString()), so you can very easily remove the dependency on MFC if you so desire.

    If you're wondering about the name, I put the "SH" in the class name because MSDN states that the IProgressDialog interface is actually part of shell32.dll (and only available on Windows 2000!), and I used "SH" to indicate that it was a shell feature. I later discovered that the dialog works fine on older versions of Windows, but by that time I'd finished the code.

    CSHProgressWnd Functions


    The CSHProgressWnd constructor creates an IProgressDialog object. On a properly-working system, this will always succeed. However, you can call the IsValid() function if you want to double-check that everything worked. Note that you must initialize OLE (such as with AfxOleInit()) before constructing a CSHProgressWnd object.

    The CSHProgressWnd destructor destroys the dialog and releases the COM interface.

    Dialog setup

    Call these functions to determine how the dialog will look.

    void SetTitle ( LPCTSTR szTitle )
    Sets the text that appears in the caption bar of the progress dialog.

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

    Specifies a resource containing an AVI that will be shown in the dialog. The first function takes the HINSTANCE of the module containing the resource. The second form uses the return from AfxGetResourceHandle() as the module.

    void SetCancelMessage ( LPCTSTR szMessage )
    Sets the text that is shown on line 3 when the user clicks the Cancel button.

    void SetCalculateTime ( bool bCalculate = true )
    Sets whether the progress dialog shows an estimate of the time remaining on line 3. If you don't call SetCalculateTime(), the dialog defaults to showing the time remaining.

    void SetAllowMinimize ( bool bAllow = true )
    Sets whether the progress dialog includes a minimize button. If you don't call SetAllowMinimize(), the dialog defaults to having a minimize button. NOTE: Calling SetAllowMinimize(false) will not remove the minimize button; this appears to be a bug in the dialog implementation.

    void SetShowProgressBar ( bool bShow = true )
    Sets whether the progress dialog shows a progress bar. If you don't call SetShowProgressBar(), the dialog defaults to having a progress bar.

    Showing the dialog

    The progress dialog can be modal or modeless. Call one of these two functions to display the dialog.

    HRESULT ShowModal ( CWnd* pwndParent )
    Displays the dialog as a modal dialog. pwndParent is a pointer to the parent window. Test the return value with the SUCCEEDED() macro to determine if the dialog was created successfully. If the dialog is not created, the return value is the error returned by the IProgressDialog::StartProgressDialog() method.

    HRESULT ShowModeless ( CWnd* pwndParent )
    Same as ShowModal(), but the progress dialog is modeless instead of modal.

    Updating the progress

    void SetLineText ( DWORD dwLine, LPCTSTR szText, bool bCompactPath = false )
    Sets one of the three lines of text in the dialog. dwLine can be 1, 2, or 3. Lines 1 and 2 appear between the AVI and the progress bar, and line 3 appears under the progress bar. If you have the dialog calculate the time remaining (by calling SetCalculateTime(true)), the dialog uses line 3 to display the estimated time remaining, and that line is unavailable to SetLineText(). If you are displaying a file name or path, pass true for the third parameter to have the dialog shorten the path so it fits in the dialog.

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

    UpdateProgress() sets the dialog's progress indicator. The first form of the function sets the current and maximum progress values. These may be, for example, 0 and 100, but the exact values are up to you. You must call the first form the first time, then afterwards you can call the second form as long as your maximum progress value does not change. You may freely change the maximum value if you need to, as long as you call the first form whenever the maximum value changes.

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

    These two functions work like the previous two, except they take 64-bit numbers instead of DWORDs.

    Other functions

    bool HasUserCanceled()
    You should call HasUserCanceled() periodically during your processing, and break out if the function returns true.

    void EndDialog()
    Call EndDialog() to close the progress dialog. The CSHProgressWnd destructor will also close the dialog if it is still visible.

    void ResetTimer()
    If you want to reset the timer used by the dialog to estimate the time remaining, call ResetTimer() at the beginning of your processing loop. The dialog uses the time between calls to ResetTimer() and UpdateProgress() to calculate the time remaining. Normally you won't need to call this function; if you don't call it, the dialog will base its estimate on the time elapsed between creation of the dialog (via ShowModal() or ShowModeless()) and the first call to UpdateProgress().

    Sample code that uses 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 )))
        dlg.UpdateProgress ( 0, dwMax );
        for ( DWORD dwProgress = 0;
              dwProgress < dwMax && !dlg.HasUserCanceled();
              dwProgress += 5 )
            wsprintf ( szMsg, _T("I'm %lu%% done"), dwProgress );
            dlg.SetLineText ( 2, szMsg );
            dlg.UpdateProgress ( dwProgress );

    You can get updates to this and my other articles at


    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here


    About the Author

    Michael Dunn
    Software Developer (Senior) VMware
    United States United States
    Michael lives in sunny Mountain View, California. He started programming with an Apple //e in 4th grade, graduated from UCLA with a math degree in 1994, and immediately landed a job as a QA engineer at Symantec, working on the Norton AntiVirus team. He pretty much taught himself Windows and MFC programming, and in 1999 he designed and coded a new interface for Norton AntiVirus 2000.
    Mike has been a a developer at Napster and at his own lil' startup, Zabersoft, a development company he co-founded with offices in Los Angeles and Odense, Denmark. Mike is now a senior engineer at VMware.

    He also enjoys his hobbies of playing pinball, bike riding, photography, and Domion on Friday nights (current favorite combo: Village + double Pirate Ship). He would get his own snooker table too if they weren't so darn big! He is also sad that he's forgotten the languages he's studied: French, Mandarin Chinese, and Japanese.

    Mike was a VC MVP from 2005 to 2009.

    You may also be interested in...

    Comments and Discussions

    Questionfile download dialog box Pin
    ammupon18-Sep-08 1:04
    memberammupon18-Sep-08 1:04 
    GeneralCustom Cancel Event Pin
    Andrew Y27-Jan-06 1:11
    memberAndrew Y27-Jan-06 1:11 
    GeneralShowModal bug Pin
    Gideon712-Jan-06 6:26
    memberGideon712-Jan-06 6:26 
    GeneralRe: ShowModal bug Pin
    Gideon712-Jan-06 8:49
    memberGideon712-Jan-06 8:49 
    I did some research and figured out why the bug is happening. StartProgressDialog creates a new thread to host the progress window. When the window receives WM_DESTROY message it ought to re-enable the parent window. But it doesn't. (This the bug.) Instead, StopProgressDialog() wrongly attempts to re-enable the parent in the calling thread (our thread), after the progress window is destroyed and the progress thread has died.

    When the progress window dies, the system tries to assign a new foreground window. It cannot assign to hwndParent because StartProgressDialog (w/PROGDLG_MODAL) disabled the parent window.

    So the system hands the foreground activation to the next process that wants it in the system foreground queue. Thus we lose our right to recapture the foreground window. I'm assuming SPI_SETFOREGROUNDLOCKTIMEOUT is non-zero, which is true by default on XP and W2K3.

    What makes things really interesting is that if you happen to attach a debugger to the process (for example to try to figure out this crazy bug), USER32 changes its behavior! When a debugger is attached it always honors SetForegroundWindow. Talk about your Heisenbug Frown | :-( .

    The way to fix this bug is to insert a call to EnableWindow(hWndParent) in the WM_DESTROY handler for the progress window in the progress thread. But short of patching USER32.DLL this is impossible Frown | :-( .

    You can't even simulate modality by wrapping the progress window with ::EnableWindow(hWndParent, FALSE/TRUE). This is because the parent must be re-enable before the progress window dies to prevent losing the foreground.

    As far as I can figure, there ain't no way.
    GeneralRe: ShowModal bug Pin
    peterchen31-Jan-07 23:34
    memberpeterchen31-Jan-07 23:34 
    AnswerRe: ShowModal bug Pin
    MandatoryDefault14-Oct-09 13:20
    memberMandatoryDefault14-Oct-09 13:20 
    QuestionGreat Article - Quick Question... Pin
    robosport29-Dec-05 6:25
    memberrobosport29-Dec-05 6:25 
    JokeRe: Great Article - Quick Question... Pin
    robosport29-Dec-05 7:13
    memberrobosport29-Dec-05 7:13 
    GeneralRe: Great Article - Quick Question... Pin
    Michael Dunn31-Dec-05 11:07
    sitebuilderMichael Dunn31-Dec-05 11:07 
    GeneralRe: Great Article - Quick Question... Pin
    robosport31-Dec-05 11:38
    memberrobosport31-Dec-05 11:38 
    GeneralChanging project name Pin
    kk_vp1-Sep-05 1:06
    memberkk_vp1-Sep-05 1:06 
    GeneralRe: Changing project name Pin
    Michael Dunn1-Sep-05 6:56
    sitebuilderMichael Dunn1-Sep-05 6:56 
    GeneralProgress dialog can be re-sized Pin
    Simon Reeves25-Aug-04 7:35
    memberSimon Reeves25-Aug-04 7:35 
    QuestionDialog goes full-screen, happened to abybody ? Pin
    ohadp3-Apr-04 22:33
    memberohadp3-Apr-04 22:33 
    GeneralGreat question Pin
    VirtualM12-May-03 8:58
    memberVirtualM12-May-03 8:58 
    GeneralRe: Great question Pin
    Michael Dunn13-May-03 20:08
    sitebuilderMichael Dunn13-May-03 20:08 
    GeneralRe: Great question Pin
    pkapple7-Jan-04 0:02
    memberpkapple7-Jan-04 0:02 
    GeneralRe: Great question Pin
    peterchen31-Jan-07 23:39
    memberpeterchen31-Jan-07 23:39 
    GeneralWindows 95/98/NT Pin
    Warren Gardner22-Oct-02 12:45
    memberWarren Gardner22-Oct-02 12:45 
    GeneralRe: Windows 95/98/NT Pin
    Mr Scotty26-Feb-03 0:10
    memberMr Scotty26-Feb-03 0:10 
    Generalplatform sdk Pin
    berginan27-Jun-02 16:47
    memberberginan27-Jun-02 16:47 
    GeneralAny way to disable the CANCEL button Pin
    Greg Strauss29-Aug-01 14:32
    memberGreg Strauss29-Aug-01 14:32 
    GeneralRe: Any way to disable the CANCEL button Pin
    Mr Scotty26-Feb-03 20:49
    memberMr Scotty26-Feb-03 20:49 
    GeneralRe: Any way to disable the CANCEL button Pin
    songbo10-Feb-06 7:49
    membersongbo10-Feb-06 7:49 
    GeneralI got 33 errors Pin
    BLaZe13-Jun-01 19:17
    memberBLaZe13-Jun-01 19:17 
    GeneralRe: I got 33 errors Pin
    Michael Dunn13-Jun-01 19:38
    memberMichael Dunn13-Jun-01 19:38 
    GeneralRe: I got 33 errors Pin
    sajal4-Dec-01 11:48
    membersajal4-Dec-01 11:48 
    GeneralRe: I got 33 errors Pin
    Michael Dunn4-Dec-01 12:09
    memberMichael Dunn4-Dec-01 12:09 
    GeneralRe: I got 33 errors Pin
    Griv9-May-04 22:56
    memberGriv9-May-04 22:56 
    GeneralUndeclared Identifier Pin
    Shane Whitfield30-Mar-01 12:47
    memberShane Whitfield30-Mar-01 12:47 
    GeneralRe: Undeclared Identifier Pin
    Alex Blekhman8-Apr-01 21:12
    memberAlex Blekhman8-Apr-01 21:12 
    GeneralProblem with NT4, IE5.0 Pin
    Alex Blekhman29-Mar-01 2:15
    memberAlex Blekhman29-Mar-01 2:15 
    GeneralVC++ 6 Pin
    Frank Hale19-Nov-00 18:32
    memberFrank Hale19-Nov-00 18:32 
    GeneralRe: VC++ 6 Pin
    Michael Dunn19-Nov-00 19:44
    memberMichael Dunn19-Nov-00 19:44 
    GeneralHeaders Pin
    Don Sanders4-Oct-00 13:33
    sussDon Sanders4-Oct-00 13:33 
    GeneralRe: Headers Pin
    Michael Dunn4-Oct-00 17:02
    sussMichael Dunn4-Oct-00 17:02 
    QuestionHeaders & Libs? Pin
    Steven Carleton17-Feb-00 17:12
    sussSteven Carleton17-Feb-00 17:12 
    AnswerRe: Headers & Libs? Pin
    Mike Dunn26-Feb-00 8:28
    sussMike Dunn26-Feb-00 8:28 
    GeneralFantastic! Pin
    Jason Hattingh9-Feb-00 1:29
    sussJason Hattingh9-Feb-00 1:29 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Terms of Use | Mobile
    Web03 | 2.8.160208.1 | Last Updated 7 Feb 2000
    Article Copyright 2000 by Michael Dunn
    Everything else Copyright © CodeProject, 1999-2016
    Layout: fixed | fluid