views:

68

answers:

1

Hi,

I'm writing a Windows CE application in C++ directly applying the WINAPI. In this application I parse a text file, which may or may not be large and thus may or may not take a while to load; and as I will add functionality to load files across the wireless network, I figured it would be best to add a progress bar.

My aim is to display the progress bar in a modal dialog, thereby preventing the user from interacting with the main window. A thread is then created to perform the loading in the background, leaving the main thread to update the GUI.

However, using EndDialog() prevents me to return to the code which loads the file until the dialog has been closed. Obviously I want to show the dialog and then load the load, periodically updating the progress from the background thread. At this point I only know of two options to circumvent this:

  1. Create the dialog using CreateDialog, modify the message handler to accommodate messages designated to the dialog, disable the main window and lastly create the background thread.
  2. Create the background thread in a suspended initial state, create the dialog using DialogBoxParam passing along the thread ID, and when capturing the WM_INITDIALOG resume the thread.

Although any of these two would probably work (I'm leaning towards the second option), I'm curious about whether this is the way progress bars are supposed to be handled in a Windows environment -- or if there is a leaner, more clever way of doing it.

A: 

You don't have to do anything particularly tricky or unusual. Just create the modal dialog box with DialogBox(). In the WM_INITDIALOG handler of your dialog box procedure, create the background thread to load the file. As the loading progresses, send the PBM_SETPOS message to the progress bar control to update it.

When the loading completes, call EndDialog() to close the dialog box. However, EndDialog() must be called from within your dialog procedure. So to do that, you need to send a dummy message (e.g. WM_APP):

DialogBox(..., DlgProc);
// File loading is done and dialog box is gone now
...
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT msg, LPARAM lparam, WPARAM wparam)
{
    switch(msg)
    {
    case WM_INITDIALOG:
        CreateThread(..., LoadingThread, ...);
        return TRUE;

    case WM_APP:
        EndDialog(hwnd);
        return TRUE;
    ...
    }

    return FALSE:
}

DWORD WINAPI LoadingThread(LPVOID param)
{
    // Load the file
    while(!done)
    {
        ...
        SendMessage(hwndProgressBar, PBM_SETPOS, progress, 0);
    }

    SendMessage(hwndDialogBox, WM_APP, 0, 0);
    return 0;
}
Adam Rosenfield
This is pretty much exactly what I'm doing (option 2), except that I've chosen to move the setup and creation of the thread outside the dialog. The reason for this is that I've isolated the whole progress bar dialog in its own class and don't want to have any back-end related functionality in there. I wouldn't really call that particularily "fancy". ^^
gablin