Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: src/engine/UpdateInstallDialog.cpp

Issue 11304082: Download updates automatically, ask to install from a modeless dialog (Closed)
Left Patch Set: Created July 31, 2013, 7:16 p.m.
Right Patch Set: Calculate sizes dynamically Created Aug. 2, 2013, 10:47 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/engine/UpdateInstallDialog.h ('k') | src/engine/Updater.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #include <sstream> 1 #include <sstream>
2 #include <string> 2 #include <string>
3 #include <Windows.h> 3 #include <Windows.h>
4 4
5 #include "../shared/Dictionary.h" 5 #include "../shared/Dictionary.h"
6 #include "../shared/Utils.h" 6 #include "../shared/Utils.h"
7 #include "UpdateInstallDialog.h" 7 #include "UpdateInstallDialog.h"
8 8
9 namespace 9 namespace
10 { 10 {
11 LRESULT CALLBACK ProcessWindowMessage(HWND window, UINT message, 11 LRESULT CALLBACK ProcessWindowMessage(HWND window, UINT message,
12 WPARAM wParam, LPARAM lParam) 12 WPARAM wParam, LPARAM lParam)
13 { 13 {
14 switch (message) 14 switch (message)
15 { 15 {
16 case WM_CLOSE: 16 case WM_CLOSE:
17 PostQuitMessage(0); 17 PostQuitMessage(1);
18 return 0; 18 return 0;
19 case WM_COMMAND: 19 case WM_COMMAND:
20 switch (LOWORD(wParam)) 20 switch (LOWORD(wParam))
21 { 21 {
22 case IDYES: 22 case IDYES:
23 PostQuitMessage(1); 23 PostQuitMessage(0);
24 return 0; 24 return 0;
25 case IDNO: 25 case IDNO:
26 PostQuitMessage(0); 26 PostQuitMessage(1);
27 return 0; 27 return 0;
28 } 28 }
29 break; 29 break;
30 } 30 }
31 return DefWindowProc(window, message, wParam, lParam); 31 return DefWindowProc(window, message, wParam, lParam);
32 } 32 }
33
34 HWND CreateDialogWindow()
35 {
36 const std::wstring windowClassName = L"ABP_UPDATE_INSTALL_DIALOG";
37 WNDCLASSEXW windowClass = {};
38 windowClass.cbSize = sizeof(windowClass);
39 windowClass.lpfnWndProc = ProcessWindowMessage;
40 windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_MENU + 1);
41 windowClass.lpszClassName = windowClassName.c_str();
42 RegisterClassEx(&windowClass);
43
44 Dictionary* dictionary = Dictionary::GetInstance();
45 std::wstring title =
46 dictionary->Lookup("updater", "install-question-title");
47
48 return CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
49 windowClassName.c_str(), title.c_str(), WS_SYSMENU,
50 0, 0, 0, 0, 0, 0, 0, 0);
51 }
52
53 int GetAverageCharacterWidth(HDC deviceContext)
54 {
55 std::wstring alphabet;
56 for (wchar_t letter = L'A'; letter != 'Z'; letter++)
57 alphabet += letter;
58 RECT alphabetRect = {};
59 DrawTextW(deviceContext, alphabet.c_str(), -1, &alphabetRect,
60 DT_CALCRECT | DT_NOPREFIX);
61 return alphabetRect.right / alphabet.length();
62 }
63
64 HWND CreateText(HWND parent)
65 {
66 Dictionary* dictionary = Dictionary::GetInstance();
67 std::wstring text = dictionary->Lookup("updater", "install-question-text");
68
69 HDC deviceContext = GetDC(parent);
70 const int characterWidth = GetAverageCharacterWidth(deviceContext);
71 const int lineLength = 40;
72 const int textWidth = lineLength * characterWidth;
73
74 RECT textRect = {};
75 textRect.right = textWidth;
76 DrawTextW(deviceContext, text.c_str(), -1, &textRect,
77 DT_CALCRECT | DT_NOPREFIX | DT_WORDBREAK);
78 const int textHeight = textRect.bottom;
79
80 return CreateWindowW(L"STATIC", text.c_str(),
81 WS_CHILD | WS_VISIBLE| SS_LEFT, 0, 0,
82 textWidth, textHeight, parent, 0, 0, 0);
83 }
84
85 HWND CreateButtons(HWND parent)
86 {
87 const std::wstring panelClassName = L"ABP_PANEL";
88 WNDCLASSW panelClass = {};
89 panelClass.lpfnWndProc =
90 reinterpret_cast<WNDPROC>(GetWindowLongPtr(parent, GWLP_WNDPROC));
91 panelClass.lpszClassName = panelClassName.c_str();
92 RegisterClass(&panelClass);
93
94 Dictionary* dictionary = Dictionary::GetInstance();
95 const std::wstring yesLabel = dictionary->Lookup("general", "button-yes");
96 const std::wstring noLabel = dictionary->Lookup("general", "button-no");
97
98 HDC deviceContext = GetDC(parent);
99 RECT yesButtonRect = {};
100 DrawTextW(deviceContext, yesLabel.c_str(), -1, &yesButtonRect,
101 DT_CALCRECT | DT_NOPREFIX);
102 RECT noButtonRect = {};
103 DrawTextW(deviceContext, noLabel.c_str(), -1, &noButtonRect,
104 DT_CALCRECT | DT_NOPREFIX);
105
106 const int minButtonWidth = 120;
107 const int minButtonHeight = 30;
108 const int buttonPadding = 5;
109 int yesButtonWidth = yesButtonRect.right + buttonPadding * 2;
110 yesButtonWidth = max(yesButtonWidth, minButtonWidth);
111 int noButtonWidth = noButtonRect.right + buttonPadding * 2;
112 noButtonWidth = max(noButtonWidth, minButtonWidth);
113 int buttonHeight = max(yesButtonRect.bottom, noButtonRect.bottom)
114 + buttonPadding * 2;
115 buttonHeight = max(buttonHeight, minButtonHeight);
116
117 const int gap = 10;
118 const int panelWidth = yesButtonWidth + gap + noButtonWidth;
119 const int panelHeight = buttonHeight;
120
121 const DWORD flags = WS_CHILD | WS_VISIBLE;
122 HWND buttons = CreateWindowW(panelClassName.c_str(), 0, flags, 0, 0,
123 panelWidth, panelHeight, parent, 0, 0, 0);
124 CreateWindowW(L"BUTTON", yesLabel.c_str(), flags,
125 0, 0, yesButtonWidth, buttonHeight,
126 buttons, reinterpret_cast<HMENU>(IDYES), 0, 0);
127 CreateWindowW(L"BUTTON", noLabel.c_str(), flags,
128 yesButtonWidth + gap, 0, noButtonWidth, buttonHeight,
129 buttons, reinterpret_cast<HMENU>(IDNO), 0, 0);
130 return buttons;
131 }
132
133 void UpdateSizes(HWND window, const HWND text, const HWND buttons)
134 {
135 RECT textRect;
136 GetWindowRect(text, &textRect);
137
138 RECT buttonsRect;
139 GetWindowRect(buttons, &buttonsRect);
140
141 const int padding = 10;
142 const int margin = 10;
143 const int gap = 10;
144 const int contentWidth = max(textRect.right, buttonsRect.right);
145 const int contentHeight = textRect.bottom + buttonsRect.bottom + margin;
146 const int windowWidth = contentWidth + padding * 2;
147 const int windowHeight = contentHeight + padding * 2;
148
149 RECT workArea;
150 SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
151 const int windowX = workArea.right - windowWidth - margin;
152 const int windowY = workArea.bottom - windowHeight - margin;
153 SetWindowPos(window, 0, windowX, windowY, windowWidth, windowHeight, 0);
154
155 const int textX = padding;
156 const int textY = padding;
157 SetWindowPos(text, 0, padding, padding, 0, 0, SWP_NOSIZE);
158
159 const int buttonsX = windowWidth - buttonsRect.right - padding;
160 const int buttonsY = windowHeight - buttonsRect.bottom - padding;
161 SetWindowPos(buttons, 0, buttonsX, buttonsY, 0, 0, SWP_NOSIZE);
162 }
33 } 163 }
34 164
35 UpdateInstallDialog::UpdateInstallDialog() 165 UpdateInstallDialog::UpdateInstallDialog()
36 { 166 {
37 const std::wstring windowClassName = L"UPDATE_INSTALL_DIALOG"; 167 window = CreateDialogWindow();
38 WNDCLASSEX windowClass = {}; 168 HWND text = CreateText(window);
Wladimir Palant 2013/08/01 09:58:24 We should use WNDCLASSEXW explicitly.
39 windowClass.cbSize = sizeof(WNDCLASSEX); 169 HWND buttons = CreateButtons(window);
Wladimir Palant 2013/08/01 09:58:24 sizeof(windowClass) to avoid repeating the type na
Felix Dahlke 2013/08/02 10:48:01 Done.
40 windowClass.lpfnWndProc = ProcessWindowMessage; 170 UpdateSizes(window, text, buttons);
41 windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_MENU + 1);
42 windowClass.lpszClassName = windowClassName.c_str();
Oleksandr 2013/08/01 07:05:12 Maybe use hIcon here with ABP logo? A default wind
43 if (!RegisterClassEx(&windowClass))
44 {
45 std::stringstream stream;
46 stream << "Failed to register window class "
47 << ToUtf8String(windowClassName) << ": " << GetLastError();
48 throw std::runtime_error(stream.str());
49 }
50
51 Dictionary* dictionary = Dictionary::GetInstance();
52 std::wstring title = dictionary->Lookup("updater", "install-question-title");
Oleksandr 2013/07/31 22:16:59 This is fine only for when download is ready. How
Felix Dahlke 2013/08/01 07:21:17 Like I said earlier, I think it's better to focus
53
54 RECT workArea;
55 SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
56
57 const int width = 300;
58 const int height = 150;
Wladimir Palant 2013/08/01 09:58:24 Where do these numbers come from? What will happen
Felix Dahlke 2013/08/02 10:48:01 Done.
59 const int margin = 10;
60
61 window = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
62 windowClassName.c_str(), title.c_str(), WS_SYSMENU,
63 workArea.right - width - margin,
64 workArea.bottom - height - margin,
65 width, height, 0, 0, 0, 0);
Oleksandr 2013/08/01 07:05:12 Should we do something like: SetForegroundWindow(
66 CreateText();
67 CreateButtons();
Oleksandr 2013/07/31 22:16:59 No CreateButtons() in the overridden constructor I
Felix Dahlke 2013/08/01 07:21:17 As I said above, let's make this more generic when
68 } 171 }
69 172
70 UpdateInstallDialog::~UpdateInstallDialog() 173 UpdateInstallDialog::~UpdateInstallDialog()
71 { 174 {
72 DestroyWindow(window); 175 DestroyWindow(window);
73 } 176 }
74 177
75 bool UpdateInstallDialog::Show() 178 bool UpdateInstallDialog::Show()
76 { 179 {
77 ShowWindow(window, SW_SHOW); 180 ShowWindow(window, SW_SHOW);
78 MSG message; 181 MSG message;
79 while(GetMessage(&message, 0, 0, 0) > 0) 182 while(GetMessage(&message, 0, 0, 0) > 0)
80 { 183 {
81 TranslateMessage(&message); 184 TranslateMessage(&message);
82 DispatchMessage(&message); 185 DispatchMessage(&message);
83 } 186 }
84 ShowWindow(window, SW_HIDE); 187 ShowWindow(window, SW_HIDE);
85 return message.wParam; 188 return message.wParam == 0;
Wladimir Palant 2013/08/01 09:58:24 Doesn't this cause a warning? I would rather cast
Felix Dahlke 2013/08/02 10:48:01 Done. Opted for message.wParam == 0 in case of yes
86 } 189 }
87
88 void UpdateInstallDialog::CreateText()
89 {
90 Dictionary* dictionary = Dictionary::GetInstance();
91 std::wstring text = dictionary->Lookup("updater", "install-question-text");
92
93 RECT clientRect;
94 GetClientRect(window, &clientRect);
95
96 const int margin = 10;
97 const int width = clientRect.right - margin * 2;
98 const int height = 60;
99
100 CreateWindowW(L"STATIC", text.c_str(), WS_CHILD | WS_VISIBLE| SS_LEFT,
101 margin, margin, width, height, window, 0, 0, 0);
102 }
103
104 void UpdateInstallDialog::CreateButtons()
105 {
106 Dictionary* dictionary = Dictionary::GetInstance();
107 const std::wstring yesLabel = dictionary->Lookup("general", "button-yes");
108 const std::wstring noLabel = dictionary->Lookup("general", "button-no");
109
110 const DWORD buttonFlags = WS_CHILD | WS_VISIBLE;
111
112 RECT clientRect;
113 GetClientRect(window, &clientRect);
114
115 const int buttonWidth = 100;
116 const int buttonHeight = 30;
Felix Dahlke 2013/08/02 10:48:01 Done.
117 const int margin = 10;
118 const int combinedWidth = buttonWidth * 2 + margin;
119 const int yesButtonX = clientRect.right - combinedWidth - margin;
120 const int noButtonX = yesButtonX + buttonWidth + margin;
121 const int buttonY = clientRect.bottom - buttonHeight - margin;
122
123 CreateWindowW(L"BUTTON", yesLabel.c_str(), buttonFlags,
124 yesButtonX, buttonY, buttonWidth, buttonHeight,
125 window, reinterpret_cast<HMENU>(IDYES), 0, 0);
126 CreateWindowW(L"BUTTON", noLabel.c_str(), buttonFlags,
127 noButtonX, buttonY, buttonWidth, buttonHeight,
128 window, reinterpret_cast<HMENU>(IDNO), 0, 0);
129 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld