1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/mozapps/update/updater/progressui_win.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,275 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include <stdio.h> 1.11 +#include <windows.h> 1.12 +#include <commctrl.h> 1.13 +#include <process.h> 1.14 +#include <io.h> 1.15 + 1.16 +#include "resource.h" 1.17 +#include "progressui.h" 1.18 +#include "readstrings.h" 1.19 +#include "errors.h" 1.20 + 1.21 +#define TIMER_ID 1 1.22 +#define TIMER_INTERVAL 100 1.23 + 1.24 +#define RESIZE_WINDOW(hwnd, extrax, extray) \ 1.25 + { \ 1.26 + RECT windowSize; \ 1.27 + GetWindowRect(hwnd, &windowSize); \ 1.28 + SetWindowPos(hwnd, 0, 0, 0, windowSize.right - windowSize.left + extrax, \ 1.29 + windowSize.bottom - windowSize.top + extray, \ 1.30 + SWP_NOMOVE | SWP_NOZORDER); \ 1.31 + } 1.32 + 1.33 +#define MOVE_WINDOW(hwnd, dx, dy) \ 1.34 + { \ 1.35 + RECT rc; \ 1.36 + POINT pt; \ 1.37 + GetWindowRect(hwnd, &rc); \ 1.38 + pt.x = rc.left; \ 1.39 + pt.y = rc.top; \ 1.40 + ScreenToClient(GetParent(hwnd), &pt); \ 1.41 + SetWindowPos(hwnd, 0, pt.x + dx, pt.y + dy, 0, 0, \ 1.42 + SWP_NOSIZE | SWP_NOZORDER); \ 1.43 + } 1.44 + 1.45 +static float sProgress; // between 0 and 100 1.46 +static BOOL sQuit = FALSE; 1.47 +static BOOL sIndeterminate = FALSE; 1.48 +static StringTable sUIStrings; 1.49 + 1.50 +static BOOL 1.51 +GetStringsFile(WCHAR filename[MAX_PATH]) 1.52 +{ 1.53 + if (!GetModuleFileNameW(nullptr, filename, MAX_PATH)) 1.54 + return FALSE; 1.55 + 1.56 + WCHAR *dot = wcsrchr(filename, '.'); 1.57 + if (!dot || wcsicmp(dot + 1, L"exe")) 1.58 + return FALSE; 1.59 + 1.60 + wcscpy(dot + 1, L"ini"); 1.61 + return TRUE; 1.62 +} 1.63 + 1.64 +static void 1.65 +UpdateDialog(HWND hDlg) 1.66 +{ 1.67 + int pos = int(sProgress + 0.5f); 1.68 + HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS); 1.69 + SendMessage(hWndPro, PBM_SETPOS, pos, 0L); 1.70 +} 1.71 + 1.72 +// The code in this function is from MSDN: 1.73 +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/usingdialogboxes.asp 1.74 +static void 1.75 +CenterDialog(HWND hDlg) 1.76 +{ 1.77 + RECT rc, rcOwner, rcDlg; 1.78 + 1.79 + // Get the owner window and dialog box rectangles. 1.80 + HWND desktop = GetDesktopWindow(); 1.81 + 1.82 + GetWindowRect(desktop, &rcOwner); 1.83 + GetWindowRect(hDlg, &rcDlg); 1.84 + CopyRect(&rc, &rcOwner); 1.85 + 1.86 + // Offset the owner and dialog box rectangles so that 1.87 + // right and bottom values represent the width and 1.88 + // height, and then offset the owner again to discard 1.89 + // space taken up by the dialog box. 1.90 + 1.91 + OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); 1.92 + OffsetRect(&rc, -rc.left, -rc.top); 1.93 + OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); 1.94 + 1.95 + // The new position is the sum of half the remaining 1.96 + // space and the owner's original position. 1.97 + 1.98 + SetWindowPos(hDlg, 1.99 + HWND_TOP, 1.100 + rcOwner.left + (rc.right / 2), 1.101 + rcOwner.top + (rc.bottom / 2), 1.102 + 0, 0, // ignores size arguments 1.103 + SWP_NOSIZE); 1.104 +} 1.105 + 1.106 +static void 1.107 +InitDialog(HWND hDlg) 1.108 +{ 1.109 + WCHAR szwTitle[MAX_TEXT_LEN]; 1.110 + WCHAR szwInfo[MAX_TEXT_LEN]; 1.111 + 1.112 + MultiByteToWideChar(CP_UTF8, 0, sUIStrings.title, -1, szwTitle, 1.113 + sizeof(szwTitle)/sizeof(szwTitle[0])); 1.114 + MultiByteToWideChar(CP_UTF8, 0, sUIStrings.info, -1, szwInfo, 1.115 + sizeof(szwInfo)/sizeof(szwInfo[0])); 1.116 + 1.117 + SetWindowTextW(hDlg, szwTitle); 1.118 + SetWindowTextW(GetDlgItem(hDlg, IDC_INFO), szwInfo); 1.119 + 1.120 + // Set dialog icon 1.121 + HICON hIcon = LoadIcon(GetModuleHandle(nullptr), 1.122 + MAKEINTRESOURCE(IDI_DIALOG)); 1.123 + if (hIcon) 1.124 + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon); 1.125 + 1.126 + HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS); 1.127 + SendMessage(hWndPro, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); 1.128 + if (sIndeterminate) { 1.129 + LONG_PTR val = GetWindowLongPtr(hWndPro, GWL_STYLE); 1.130 + SetWindowLongPtr(hWndPro, GWL_STYLE, val|PBS_MARQUEE); 1.131 + SendMessage(hWndPro,(UINT) PBM_SETMARQUEE,(WPARAM) TRUE,(LPARAM)50 ); 1.132 + } 1.133 + 1.134 + // Resize the dialog to fit all of the text if necessary. 1.135 + RECT infoSize, textSize; 1.136 + HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO); 1.137 + 1.138 + // Get the control's font for calculating the new size for the control 1.139 + HDC hDCInfo = GetDC(hWndInfo); 1.140 + HFONT hInfoFont, hOldFont; 1.141 + hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0); 1.142 + 1.143 + if (hInfoFont) 1.144 + hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont); 1.145 + 1.146 + // Measure the space needed for the text on a single line. DT_CALCRECT means 1.147 + // nothing is drawn. 1.148 + if (DrawText(hDCInfo, szwInfo, -1, &textSize, 1.149 + DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE)) { 1.150 + GetClientRect(hWndInfo, &infoSize); 1.151 + SIZE extra; 1.152 + // Calculate the additional space needed for the text by subtracting from 1.153 + // the rectangle returned by DrawText the existing client rectangle's width 1.154 + // and height. 1.155 + extra.cx = (textSize.right - textSize.left) - \ 1.156 + (infoSize.right - infoSize.left); 1.157 + extra.cy = (textSize.bottom - textSize.top) - \ 1.158 + (infoSize.bottom - infoSize.top); 1.159 + if (extra.cx < 0) 1.160 + extra.cx = 0; 1.161 + if (extra.cy < 0) 1.162 + extra.cy = 0; 1.163 + if ((extra.cx > 0) || (extra.cy > 0)) { 1.164 + RESIZE_WINDOW(hDlg, extra.cx, extra.cy); 1.165 + RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy); 1.166 + RESIZE_WINDOW(hWndPro, extra.cx, 0); 1.167 + MOVE_WINDOW(hWndPro, 0, extra.cy); 1.168 + } 1.169 + } 1.170 + 1.171 + if (hOldFont) 1.172 + SelectObject(hDCInfo, hOldFont); 1.173 + 1.174 + ReleaseDC(hWndInfo, hDCInfo); 1.175 + 1.176 + CenterDialog(hDlg); // make dialog appear in the center of the screen 1.177 + 1.178 + SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, nullptr); 1.179 +} 1.180 + 1.181 +// Message handler for update dialog. 1.182 +static LRESULT CALLBACK 1.183 +DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 1.184 +{ 1.185 + switch (message) 1.186 + { 1.187 + case WM_INITDIALOG: 1.188 + InitDialog(hDlg); 1.189 + return TRUE; 1.190 + 1.191 + case WM_TIMER: 1.192 + if (sQuit) { 1.193 + EndDialog(hDlg, 0); 1.194 + } else { 1.195 + UpdateDialog(hDlg); 1.196 + } 1.197 + return TRUE; 1.198 + 1.199 + case WM_COMMAND: 1.200 + return TRUE; 1.201 + } 1.202 + return FALSE; 1.203 +} 1.204 + 1.205 +int 1.206 +InitProgressUI(int *argc, NS_tchar ***argv) 1.207 +{ 1.208 + return 0; 1.209 +} 1.210 + 1.211 +/** 1.212 + * Initializes the progress UI strings 1.213 + * 1.214 + * @return 0 on success, -1 on error 1.215 +*/ 1.216 +int 1.217 +InitProgressUIStrings() { 1.218 + // If we do not have updater.ini, then we should not bother showing UI. 1.219 + WCHAR filename[MAX_PATH]; 1.220 + if (!GetStringsFile(filename)) { 1.221 + return -1; 1.222 + } 1.223 + 1.224 + if (_waccess(filename, 04)) { 1.225 + return -1; 1.226 + } 1.227 + 1.228 + // If the updater.ini doesn't have the required strings, then we should not 1.229 + // bother showing UI. 1.230 + if (ReadStrings(filename, &sUIStrings) != OK) { 1.231 + return -1; 1.232 + } 1.233 + 1.234 + return 0; 1.235 +} 1.236 + 1.237 +int 1.238 +ShowProgressUI(bool indeterminate, bool initUIStrings) 1.239 +{ 1.240 + sIndeterminate = indeterminate; 1.241 + if (!indeterminate) { 1.242 + // Only show the Progress UI if the process is taking a significant amount of 1.243 + // time where a significant amount of time is defined as .5 seconds after 1.244 + // ShowProgressUI is called sProgress is less than 70. 1.245 + Sleep(500); 1.246 + 1.247 + if (sQuit || sProgress > 70.0f) 1.248 + return 0; 1.249 + } 1.250 + 1.251 + if (initUIStrings && InitProgressUIStrings() == -1) { 1.252 + return -1; 1.253 + } 1.254 + 1.255 + INITCOMMONCONTROLSEX icc = { 1.256 + sizeof(INITCOMMONCONTROLSEX), 1.257 + ICC_PROGRESS_CLASS 1.258 + }; 1.259 + InitCommonControlsEx(&icc); 1.260 + 1.261 + DialogBox(GetModuleHandle(nullptr), 1.262 + MAKEINTRESOURCE(IDD_DIALOG), nullptr, 1.263 + (DLGPROC) DialogProc); 1.264 + 1.265 + return 0; 1.266 +} 1.267 + 1.268 +void 1.269 +QuitProgressUI() 1.270 +{ 1.271 + sQuit = TRUE; 1.272 +} 1.273 + 1.274 +void 1.275 +UpdateProgressUI(float progress) 1.276 +{ 1.277 + sProgress = progress; // 32-bit writes are atomic 1.278 +}