user1715408
user1715408

Reputation:

How to create a progress bar while downloading a file using the windows API?

i'm working on an application in MS Visual C++ using Windows API that must download a file and place it in a folder.

I have already implemented the download using URLDownloadToFile function, but i want to create a PROGRESS_CLASS progress bar with marquee style while the file is being downloaded, but it doesn't seems to get animated in the process.

This is the function I use for downloading:

BOOL SOXDownload()
{   
    HRESULT hRez = URLDownloadToFile(NULL,
        "url","C:\\sox.zip", 0, NULL);
    if (hRez == E_OUTOFMEMORY ) {
        MessageBox(hWnd, "Out of memory Error","", MB_OK);
        return FALSE;
    }
    if (hRez != S_OK) {
        MessageBox(hWnd, "Error downloading sox.", "Error!", MB_ICONERROR | MB_SYSTEMMODAL);
        return FALSE;
    }
    if (hRez == S_OK) {
        BSTR file = SysAllocString(L"C:\\sox.zip");
        BSTR folder = SysAllocString(L"C:\\");
        Unzip2Folder(file, folder);
        ::MessageBoxA(hWnd, "Sox Binaries downloaded succesfully", "Success", MB_OK);
    }
    return TRUE;
}

Later I call inside WM_CREATE (in my main window's message processor):

if (!fileExists("C:\\SOX\\SOX.exe")) {
    components[7] = CreateWindowEx(0, PROGRESS_CLASS,
                                NULL, WS_VISIBLE | PBS_MARQUEE,
                                GetSystemMetrics(SM_CXSCREEN) / 2 - 80,
                                GetSystemMetrics(SM_CYSCREEN) / 2 + 25,
                                200, 50, hWnd, NULL, NULL, NULL);
    SetWindowText(components[7], "Downloading SoX");
    SendMessage(components[7], PBM_SETRANGE, 0, (LPARAM) MAKELPARAM(0, 50));
    SendMessage(components[7], PBM_SETMARQUEE, TRUE, MAKELPARAM( 0, 50));
    SOXDownload();
    SendMessage(components[7], WM_CLOSE, NULL, NULL);
}

And as I want, I get a tiny progress bar... But it's not animated, and when I place the cursor over the bar, the cursor indicates that the program is busy downloading the file.

When the download is complete, the window closes as i requested: SendMessage(components[7], WM_CLOSE, NULL, NULL);

So the question is how can I make the bar move while downloading the file? Considering that i want it done with marquee style for simplicity.

Thanks in advance.

Upvotes: 0

Views: 4114

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 596352

Create a class that implements the IBindStatusCallback interface and then pass it to the last parameter of URLDownloadToFile(). You will then receive OnProgress events during the download, which you can use to update your UI as needed, pump the message queue for pending messages, etc.

Upvotes: 3

Jerry Coffin
Jerry Coffin

Reputation: 490148

I think I'd use InternetReadFile (or InternetReadFileEx). This will let you read a small amount at a time (e.g., 4 kilobytes) so you can update your status bar periodically (and handle any other messages as well).

To maximize UI responsiveness, you can do an asynchronous read. This will let you process messages immediately during the download instead of waiting for the next 4K (or whatever) block to finish. Over a fast connection, it probably won't make a noticeable difference (4K doesn't normally take long) but over a slow or undependable connection, it could be a fairly major help. Doing asynchronous downloading also gives you a chance to cleanly cancel the transaction if it takes too long.

Upvotes: 0

Related Questions