Reputation:
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
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
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