+// DownloadManager
+
+PAPPLICATION_INFO DownloadManager::AppInfo = NULL;
+
+INT_PTR CALLBACK DownloadManager::DownloadDlgProc(HWND Dlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE Thread;
+ DWORD ThreadId;
+ HWND Item;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ HICON hIconSm, hIconBg;
+ WCHAR szCaption[MAX_PATH];
+ ATL::CStringW szNewCaption;
+
+ hIconBg = (HICON) GetClassLongW(hMainWnd, GCLP_HICON);
+ hIconSm = (HICON) GetClassLongW(hMainWnd, GCLP_HICONSM);
+
+ if (hIconBg && hIconSm)
+ {
+ SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) hIconBg);
+ SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSm);
+ }
+
+ // Change caption to show the currently downloaded app
+ GetWindowTextW(Dlg, szCaption, MAX_PATH);
+ szNewCaption.Format(szCaption, AppInfo->szName.GetString());
+ SetWindowTextW(Dlg, szNewCaption.GetString());
+
+ SetWindowLongW(Dlg, GWLP_USERDATA, 0);
+ Item = GetDlgItem(Dlg, IDC_DOWNLOAD_PROGRESS);
+ if (Item)
+ {
+ // initialize the default values for our nifty progress bar
+ // and subclass it so that it learns to print a status text
+ SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
+ SendMessageW(Item, PBM_SETPOS, 0, 0);
+
+ SetWindowSubclass(Item, DownloadProgressProc, 0, 0);
+ }
+
+ // add a neat placeholder until the download URL is retrieved
+ SetDlgItemTextW(Dlg, IDC_DOWNLOAD_STATUS, L"\x2022 \x2022 \x2022");
+
+ Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
+ if (!Thread)
+ return FALSE;
+ CloseHandle(Thread);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ if (wParam == IDCANCEL)
+ {
+ SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
+ PostMessageW(Dlg, WM_CLOSE, 0, 0);
+ }
+ return FALSE;
+
+ case WM_CLOSE:
+ DestroyWindow(Dlg);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+LRESULT CALLBACK DownloadManager::DownloadProgressProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+{
+ static ATL::CStringW szProgressText;
+
+ switch (uMsg)
+ {
+ case WM_SETTEXT:
+ {
+ if (lParam)
+ {
+ szProgressText = (PCWSTR) lParam;
+ }
+ return TRUE;
+ }
+
+ case WM_ERASEBKGND:
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC = BeginPaint(hWnd, &ps), hdcMem;
+ HBITMAP hbmMem;
+ HANDLE hOld;
+ RECT myRect;
+ UINT win_width, win_height;
+
+ GetClientRect(hWnd, &myRect);
+
+ /* grab the progress bar rect size */
+ win_width = myRect.right - myRect.left;
+ win_height = myRect.bottom - myRect.top;
+
+ /* create an off-screen DC for double-buffering */
+ hdcMem = CreateCompatibleDC(hDC);
+ hbmMem = CreateCompatibleBitmap(hDC, win_width, win_height);
+
+ hOld = SelectObject(hdcMem, hbmMem);
+
+ /* call the original draw code and redirect it to our memory buffer */
+ DefSubclassProc(hWnd, uMsg, (WPARAM) hdcMem, lParam);
+
+ /* draw our nifty progress text over it */
+ SelectFont(hdcMem, GetStockFont(DEFAULT_GUI_FONT));
+ DrawShadowText(hdcMem, szProgressText.GetString(), szProgressText.GetLength(),
+ &myRect,
+ DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE,
+ GetSysColor(COLOR_CAPTIONTEXT),
+ GetSysColor(COLOR_3DSHADOW),
+ 1, 1);
+
+ /* transfer the off-screen DC to the screen */
+ BitBlt(hDC, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);
+
+ /* free the off-screen DC */
+ SelectObject(hdcMem, hOld);
+ DeleteObject(hbmMem);
+ DeleteDC(hdcMem);
+
+ EndPaint(hWnd, &ps);
+ return 0;
+ }
+
+ /* Raymond Chen says that we should safely unsubclass all the things!
+ (http://blogs.msdn.com/b/oldnewthing/archive/2003/11/11/55653.aspx) */
+ case WM_NCDESTROY:
+ {
+ szProgressText.Empty();
+ RemoveWindowSubclass(hWnd, DownloadProgressProc, uIdSubclass);
+ }
+ /* Fall-through */
+ default:
+ return DefSubclassProc(hWnd, uMsg, wParam, lParam);
+ }
+}
+
+DWORD WINAPI DownloadManager::ThreadFunc(LPVOID Context)