aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-08-01 09:36:12 -0600
committerSean Hall <r.sean.hall@gmail.com>2020-08-09 10:33:49 -0600
commit3f8e35223216ebbe7f6683a5031a5a97bbc66d5a (patch)
tree2cd73b5fab393dc6c4d6cca5da481ef6bbaf4518
parentd21eed76c48960707561c45c492c10a6a23c052e (diff)
downloadwix-3f8e35223216ebbe7f6683a5031a5a97bbc66d5a.tar.gz
wix-3f8e35223216ebbe7f6683a5031a5a97bbc66d5a.tar.bz2
wix-3f8e35223216ebbe7f6683a5031a5a97bbc66d5a.zip
Update splash screen to be per-monitor DPI aware.
Remove GDI+ from engine since the higher quality scaling isn't worth the additional dependency.
-rw-r--r--src/WixToolset.BootstrapperCore.Native/WixToolset.BootstrapperCore.Native.proj2
-rw-r--r--src/engine/engine.cpp9
-rw-r--r--src/engine/engine.vcxproj4
-rw-r--r--src/engine/packages.config2
-rw-r--r--src/engine/precomp.h7
-rw-r--r--src/engine/splashscreen.cpp277
-rw-r--r--src/stub/packages.config2
-rw-r--r--src/stub/stub.vcxproj6
-rw-r--r--src/test/BurnUnitTest/BurnUnitTest.vcxproj6
-rw-r--r--src/test/BurnUnitTest/packages.config2
10 files changed, 180 insertions, 137 deletions
diff --git a/src/WixToolset.BootstrapperCore.Native/WixToolset.BootstrapperCore.Native.proj b/src/WixToolset.BootstrapperCore.Native/WixToolset.BootstrapperCore.Native.proj
index 113fe7ae..c0a99472 100644
--- a/src/WixToolset.BootstrapperCore.Native/WixToolset.BootstrapperCore.Native.proj
+++ b/src/WixToolset.BootstrapperCore.Native/WixToolset.BootstrapperCore.Native.proj
@@ -1,4 +1,4 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4 4
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
index 71c37138..ae5b690c 100644
--- a/src/engine/engine.cpp
+++ b/src/engine/engine.cpp
@@ -89,6 +89,7 @@ extern "C" HRESULT EngineRun(
89 BOOL fComInitialized = FALSE; 89 BOOL fComInitialized = FALSE;
90 BOOL fLogInitialized = FALSE; 90 BOOL fLogInitialized = FALSE;
91 BOOL fCrypInitialized = FALSE; 91 BOOL fCrypInitialized = FALSE;
92 BOOL fDpiuInitialized = FALSE;
92 BOOL fRegInitialized = FALSE; 93 BOOL fRegInitialized = FALSE;
93 BOOL fWiuInitialized = FALSE; 94 BOOL fWiuInitialized = FALSE;
94 BOOL fXmlInitialized = FALSE; 95 BOOL fXmlInitialized = FALSE;
@@ -132,6 +133,9 @@ extern "C" HRESULT EngineRun(
132 ExitOnFailure(hr, "Failed to initialize Cryputil."); 133 ExitOnFailure(hr, "Failed to initialize Cryputil.");
133 fCrypInitialized = TRUE; 134 fCrypInitialized = TRUE;
134 135
136 DpiuInitialize();
137 fDpiuInitialized = TRUE;
138
135 hr = RegInitialize(); 139 hr = RegInitialize();
136 ExitOnFailure(hr, "Failed to initialize Regutil."); 140 ExitOnFailure(hr, "Failed to initialize Regutil.");
137 fRegInitialized = TRUE; 141 fRegInitialized = TRUE;
@@ -241,6 +245,11 @@ LExit:
241 RegUninitialize(); 245 RegUninitialize();
242 } 246 }
243 247
248 if (fDpiuInitialized)
249 {
250 DpiuUninitialize();
251 }
252
244 if (fCrypInitialized) 253 if (fCrypInitialized)
245 { 254 {
246 CrypUninitialize(); 255 CrypUninitialize();
diff --git a/src/engine/engine.vcxproj b/src/engine/engine.vcxproj
index 906792a6..ef5c1602 100644
--- a/src/engine/engine.vcxproj
+++ b/src/engine/engine.vcxproj
@@ -2,7 +2,7 @@
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 3
4<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 4<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <Import Project="..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props')" /> 5 <Import Project="..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props')" />
6 6
7 <ItemGroup Label="ProjectConfigurations"> 7 <ItemGroup Label="ProjectConfigurations">
8 <ProjectConfiguration Include="Debug|Win32"> 8 <ProjectConfiguration Include="Debug|Win32">
@@ -165,7 +165,7 @@ rc.exe -fo "$(OutDir)engine.res" "$(IntDir)engine.messages.rc"</Command>
165 <PropertyGroup> 165 <PropertyGroup>
166 <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> 166 <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
167 </PropertyGroup> 167 </PropertyGroup>
168 <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props'))" /> 168 <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props'))" />
169 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets'))" /> 169 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets'))" />
170 </Target> 170 </Target>
171</Project> 171</Project>
diff --git a/src/engine/packages.config b/src/engine/packages.config
index 04a6553e..e7fa32d0 100644
--- a/src/engine/packages.config
+++ b/src/engine/packages.config
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<packages> 2<packages>
3 <package id="Nerdbank.GitVersioning" version="3.1.91" targetFramework="native" developmentDependency="true" /> 3 <package id="Nerdbank.GitVersioning" version="3.1.91" targetFramework="native" developmentDependency="true" />
4 <package id="WixToolset.DUtil" version="4.0.45" targetFramework="native" /> 4 <package id="WixToolset.DUtil" version="4.0.49" targetFramework="native" />
5</packages> \ No newline at end of file 5</packages> \ No newline at end of file
diff --git a/src/engine/precomp.h b/src/engine/precomp.h
index c60d7c0e..b5c5e65e 100644
--- a/src/engine/precomp.h
+++ b/src/engine/precomp.h
@@ -6,11 +6,6 @@
6#include <aclapi.h> 6#include <aclapi.h>
7#include <Bits.h> 7#include <Bits.h>
8 8
9#pragma warning(push)
10#pragma warning(disable:4458) // declaration of 'xxx' hides class member
11#include <gdiplus.h>
12#pragma warning(pop)
13
14#include <math.h> 9#include <math.h>
15#include <msiquery.h> 10#include <msiquery.h>
16#include <sddl.h> 11#include <sddl.h>
@@ -37,7 +32,6 @@
37#include <cryputil.h> 32#include <cryputil.h>
38#include <dirutil.h> 33#include <dirutil.h>
39#include <fileutil.h> 34#include <fileutil.h>
40#include <gdiputil.h>
41#include <guidutil.h> 35#include <guidutil.h>
42#include <logutil.h> 36#include <logutil.h>
43#include <memutil.h> 37#include <memutil.h>
@@ -60,6 +54,7 @@
60#include <dlutil.h> 54#include <dlutil.h>
61#include <atomutil.h> 55#include <atomutil.h>
62#include <apuputil.h> 56#include <apuputil.h>
57#include <dpiutil.h>
63 58
64#include "..\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" 59#include "..\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h"
65#include "..\WixToolset.BootstrapperCore.Native\inc\BootstrapperApplication.h" 60#include "..\WixToolset.BootstrapperCore.Native\inc\BootstrapperApplication.h"
diff --git a/src/engine/splashscreen.cpp b/src/engine/splashscreen.cpp
index 1f95886a..cad8c88c 100644
--- a/src/engine/splashscreen.cpp
+++ b/src/engine/splashscreen.cpp
@@ -2,8 +2,6 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5using namespace Gdiplus;
6
7#define BURN_SPLASHSCREEN_CLASS_WINDOW L"WixBurnSplashScreen" 5#define BURN_SPLASHSCREEN_CLASS_WINDOW L"WixBurnSplashScreen"
8#define IDB_SPLASHSCREEN 1 6#define IDB_SPLASHSCREEN 1
9 7
@@ -11,14 +9,16 @@ using namespace Gdiplus;
11 9
12struct SPLASHSCREEN_INFO 10struct SPLASHSCREEN_INFO
13{ 11{
14 Bitmap* pBitmap; 12 HBITMAP hBitmap;
15 Point pt; 13 SIZE defaultDpiSize;
16 Size size; 14 SIZE size;
15 UINT nDpi;
16 HWND hWnd;
17}; 17};
18 18
19struct SPLASHSCREEN_CONTEXT 19struct SPLASHSCREEN_CONTEXT
20{ 20{
21 HANDLE hIntializedEvent; 21 HANDLE hInitializedEvent;
22 HINSTANCE hInstance; 22 HINSTANCE hInstance;
23 LPCWSTR wzCaption; 23 LPCWSTR wzCaption;
24 24
@@ -36,14 +36,29 @@ static LRESULT CALLBACK WndProc(
36 __in WPARAM wParam, 36 __in WPARAM wParam,
37 __in LPARAM lParam 37 __in LPARAM lParam
38 ); 38 );
39static void OnPaint(
40 __in HDC hdc,
41 __in SPLASHSCREEN_INFO* pSplashScreen
42 );
43static HRESULT LoadSplashScreen( 39static HRESULT LoadSplashScreen(
44 __in HMODULE hInstance, 40 __in SPLASHSCREEN_CONTEXT* pContext,
45 __in SPLASHSCREEN_INFO* pSplashScreen 41 __in SPLASHSCREEN_INFO* pSplashScreen
46 ); 42 );
43static BOOL OnDpiChanged(
44 __in SPLASHSCREEN_INFO* pSplashScreen,
45 __in WPARAM wParam,
46 __in LPARAM lParam
47 );
48static void OnEraseBkgnd(
49 __in SPLASHSCREEN_INFO* pSplashScreen,
50 __in WPARAM wParam
51 );
52static void OnNcCreate(
53 __in HWND hWnd,
54 __in LPARAM lParam
55 );
56static void ScaleSplashScreen(
57 __in SPLASHSCREEN_INFO* pSplashScreen,
58 __in UINT nDpi,
59 __in int x,
60 __in int y
61 );
47 62
48 63
49// function definitions 64// function definitions
@@ -63,7 +78,7 @@ extern "C" void SplashScreenCreate(
63 ExitOnNullWithLastError(rgSplashScreenEvents[0], hr, "Failed to create modal event."); 78 ExitOnNullWithLastError(rgSplashScreenEvents[0], hr, "Failed to create modal event.");
64 79
65 // create splash screen thread. 80 // create splash screen thread.
66 context.hIntializedEvent = rgSplashScreenEvents[0]; 81 context.hInitializedEvent = rgSplashScreenEvents[0];
67 context.hInstance = hInstance; 82 context.hInstance = hInstance;
68 context.wzCaption = wzCaption; 83 context.wzCaption = wzCaption;
69 context.pHwnd = pHwnd; 84 context.pHwnd = pHwnd;
@@ -115,30 +130,17 @@ static DWORD WINAPI ThreadProc(
115 ) 130 )
116{ 131{
117 HRESULT hr = S_OK; 132 HRESULT hr = S_OK;
118
119 ULONG_PTR token = 0;
120 GdiplusStartupInput input;
121 GdiplusStartupOutput output = { };
122
123 SPLASHSCREEN_CONTEXT* pContext = static_cast<SPLASHSCREEN_CONTEXT*>(pvContext); 133 SPLASHSCREEN_CONTEXT* pContext = static_cast<SPLASHSCREEN_CONTEXT*>(pvContext);
124 SPLASHSCREEN_INFO splashScreen = { }; 134
135 SPLASHSCREEN_INFO splashScreenInfo = { };
125 136
126 WNDCLASSW wc = { }; 137 WNDCLASSW wc = { };
127 BOOL fRegistered = TRUE; 138 BOOL fRegistered = TRUE;
128 HWND hWnd = NULL;
129 139
130 BOOL fRet = FALSE; 140 BOOL fRet = FALSE;
131 MSG msg = { }; 141 MSG msg = { };
132 142
133 input.GdiplusVersion = 1; 143 // Register the window class.
134
135 hr = GdipInitialize(&input, &token, &output);
136 ExitOnFailure(hr, "Failed to initialize GDI+.");
137
138 hr = LoadSplashScreen(pContext->hInstance, &splashScreen);
139 ExitOnFailure(hr, "Failed to load splash screen.");
140
141 // Register the window class and create the window.
142 wc.lpfnWndProc = WndProc; 144 wc.lpfnWndProc = WndProc;
143 wc.hInstance = pContext->hInstance; 145 wc.hInstance = pContext->hInstance;
144 wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 146 wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
@@ -150,12 +152,12 @@ static DWORD WINAPI ThreadProc(
150 152
151 fRegistered = TRUE; 153 fRegistered = TRUE;
152 154
153 hWnd = ::CreateWindowExW(WS_EX_TOOLWINDOW, wc.lpszClassName, pContext->wzCaption, WS_POPUP | WS_VISIBLE, splashScreen.pt.X, splashScreen.pt.Y, splashScreen.size.Width, splashScreen.size.Height, HWND_DESKTOP, NULL, pContext->hInstance, &splashScreen); 155 hr = LoadSplashScreen(pContext, &splashScreenInfo);
154 ExitOnNullWithLastError(hWnd, hr, "Failed to create window."); 156 ExitOnFailure(hr, "Failed to load splash screen.");
155 157
156 // Return the splash screen window and free the main thread waiting for us to be initialized. 158 // Return the splash screen window and free the main thread waiting for us to be initialized.
157 *pContext->pHwnd = hWnd; 159 *pContext->pHwnd = splashScreenInfo.hWnd;
158 ::SetEvent(pContext->hIntializedEvent); 160 ::SetEvent(pContext->hInitializedEvent);
159 161
160 // Pump messages until the bootstrapper application destroys the window. 162 // Pump messages until the bootstrapper application destroys the window.
161 while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0))) 163 while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
@@ -165,7 +167,7 @@ static DWORD WINAPI ThreadProc(
165 hr = E_UNEXPECTED; 167 hr = E_UNEXPECTED;
166 ExitOnFailure(hr, "Unexpected return value from message pump."); 168 ExitOnFailure(hr, "Unexpected return value from message pump.");
167 } 169 }
168 else if (!::IsDialogMessageW(hWnd, &msg)) 170 else if (!::IsDialogMessageW(splashScreenInfo.hWnd, &msg))
169 { 171 {
170 ::TranslateMessage(&msg); 172 ::TranslateMessage(&msg);
171 ::DispatchMessageW(&msg); 173 ::DispatchMessageW(&msg);
@@ -178,14 +180,9 @@ LExit:
178 ::UnregisterClassW(BURN_SPLASHSCREEN_CLASS_WINDOW, pContext->hInstance); 180 ::UnregisterClassW(BURN_SPLASHSCREEN_CLASS_WINDOW, pContext->hInstance);
179 } 181 }
180 182
181 if (splashScreen.pBitmap) 183 if (splashScreenInfo.hBitmap)
182 {
183 delete splashScreen.pBitmap;
184 }
185
186 if (token)
187 { 184 {
188 GdipUninitialize(token); 185 ::DeleteObject(splashScreenInfo.hBitmap);
189 } 186 }
190 187
191 return hr; 188 return hr;
@@ -204,113 +201,155 @@ static LRESULT CALLBACK WndProc(
204 switch (uMsg) 201 switch (uMsg)
205 { 202 {
206 case WM_NCCREATE: 203 case WM_NCCREATE:
207 { 204 OnNcCreate(hWnd, lParam);
208 LPCREATESTRUCTW lpcs = reinterpret_cast<LPCREATESTRUCTW>(lParam);
209 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(lpcs->lpCreateParams));
210 }
211 break; 205 break;
212 206
213 case WM_NCDESTROY: 207 case WM_NCDESTROY:
214 lres = ::DefWindowProcW(hWnd, uMsg, wParam, lParam); 208 lres = ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
215 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0); 209 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
210 ::PostQuitMessage(0);
216 return lres; 211 return lres;
217 212
218 case WM_NCHITTEST: 213 case WM_NCHITTEST:
219 return HTCAPTION; // allow window to be moved by grabbing any pixel. 214 return HTCAPTION; // allow window to be moved by grabbing any pixel.
220 215
221 case WM_DESTROY: 216 case WM_DPICHANGED:
222 ::PostQuitMessage(0); 217 if (OnDpiChanged(pSplashScreen, wParam, lParam))
223 return 0; 218 {
219 return 0;
220 }
221 break;
224 222
225 case WM_ERASEBKGND: 223 case WM_ERASEBKGND:
226 // The splash screen image will be repainted in its entirety. 224 OnEraseBkgnd(pSplashScreen, wParam);
227 return 1; 225 return 1;
228
229 case WM_PAINT:
230 {
231 PAINTSTRUCT ps = { };
232
233 HDC hdc = BeginPaint(hWnd, &ps);
234 OnPaint(hdc, pSplashScreen);
235 EndPaint(hWnd, &ps);
236 }
237 return 0;
238 } 226 }
239 227
240 return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); 228 return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
241} 229}
242 230
243static void OnPaint(
244 __in HDC hdc,
245 __in SPLASHSCREEN_INFO* pSplashScreen
246 )
247{
248 // Use high-quality bicubuc stretching from GDI+ which looks better than GDI.
249 Graphics graphics(hdc);
250 graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
251
252 Rect dst(0, 0, pSplashScreen->size.Width, pSplashScreen->size.Height);
253 Status status = graphics.DrawImage(pSplashScreen->pBitmap, dst);
254
255#if DEBUG
256 HRESULT hr = GdipHresultFromStatus(status);
257 TraceError(hr, "Failed to draw splash screen bitmap.");
258#else
259 UNREFERENCED_PARAMETER(status);
260#endif
261}
262
263static HRESULT LoadSplashScreen( 231static HRESULT LoadSplashScreen(
264 __in HMODULE hInstance, 232 __in SPLASHSCREEN_CONTEXT* pContext,
265 __in SPLASHSCREEN_INFO* pSplashScreen 233 __in SPLASHSCREEN_INFO* pSplashScreen
266 ) 234 )
267{ 235{
268 HRESULT hr = S_OK; 236 HRESULT hr = S_OK;
269 POINT ptCursor = { }; 237 BITMAP bmp = { };
270 HMONITOR hMonitor = NULL; 238 POINT pt = { };
271 MONITORINFOEXW mi; 239 int x = 0;
272 HDC hdc = NULL; 240 int y = 0;
273 UINT dpiX = 0; 241 DPIU_MONITOR_CONTEXT* pMonitorContext = NULL;
274 UINT dpiY = 0; 242 RECT* pMonitorRect = NULL;
275 243
276 pSplashScreen->pBitmap = Bitmap::FromResource(hInstance, MAKEINTRESOURCEW(IDB_SPLASHSCREEN)); 244 pSplashScreen->nDpi = USER_DEFAULT_SCREEN_DPI;
277 ExitOnNull(pSplashScreen->pBitmap, hr, E_INVALIDDATA, "Failed to find the splash screen bitmap."); 245 pSplashScreen->hBitmap = ::LoadBitmapW(pContext->hInstance, MAKEINTRESOURCEW(IDB_SPLASHSCREEN));
278 ExitOnGdipFailure(pSplashScreen->pBitmap->GetLastStatus(), hr, "Failed to load the splash screen bitmap."); 246 ExitOnNullWithLastError(pSplashScreen->hBitmap, hr, "Failed to load splash screen bitmap.");
279 247
280 pSplashScreen->pt.X = CW_USEDEFAULT; 248 ::GetObject(pSplashScreen->hBitmap, sizeof(bmp), static_cast<void*>(&bmp));
281 pSplashScreen->pt.Y = CW_USEDEFAULT; 249 pSplashScreen->defaultDpiSize.cx = pSplashScreen->size.cx = bmp.bmWidth;
282 pSplashScreen->size.Width = pSplashScreen->pBitmap->GetWidth(); 250 pSplashScreen->defaultDpiSize.cy = pSplashScreen->size.cy = bmp.bmHeight;
283 pSplashScreen->size.Height = pSplashScreen->pBitmap->GetHeight(); 251
284 252 // Try to default to the monitor with the mouse, otherwise default to the primary monitor.
285 // Stretch and center the window on the monitor with the mouse. 253 if (!::GetCursorPos(&pt))
286 if (::GetCursorPos(&ptCursor))
287 { 254 {
288 hMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST); 255 pt.x = 0;
289 if (hMonitor) 256 pt.y = 0;
257 }
258
259 // Try to center the window on the chosen monitor.
260 hr = DpiuGetMonitorContextFromPoint(&pt, &pMonitorContext);
261 if (SUCCEEDED(hr))
262 {
263 pMonitorRect = &pMonitorContext->mi.rcWork;
264 if (pMonitorContext->nDpi != pSplashScreen->nDpi)
290 { 265 {
291 ZeroMemory(&mi, sizeof(mi)); 266 ScaleSplashScreen(pSplashScreen, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top);
292 mi.cbSize = sizeof(mi);
293
294 if (::GetMonitorInfoW(hMonitor, &mi))
295 {
296 hdc = ::CreateDCW(L"DISPLAY", mi.szDevice, NULL, NULL);
297 if (hdc)
298 {
299 dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX);
300 dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY);
301
302 pSplashScreen->size.Width = pSplashScreen->size.Width * dpiX / 96;
303 pSplashScreen->size.Height = pSplashScreen->size.Height * dpiY / 96;
304
305 ::ReleaseDC(NULL, hdc);
306 }
307
308 pSplashScreen->pt.X = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - pSplashScreen->size.Width) / 2;
309 pSplashScreen->pt.Y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - pSplashScreen->size.Height) / 2;
310 }
311 } 267 }
268
269 x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pSplashScreen->size.cx) / 2;
270 y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pSplashScreen->size.cy) / 2;
312 } 271 }
272 else
273 {
274 hr = S_OK;
275 x = CW_USEDEFAULT;
276 y = CW_USEDEFAULT;
277 }
278
279 pSplashScreen->hWnd = ::CreateWindowExW(WS_EX_TOOLWINDOW, BURN_SPLASHSCREEN_CLASS_WINDOW, pContext->wzCaption, WS_POPUP | WS_VISIBLE, x, y, pSplashScreen->size.cx, pSplashScreen->size.cy, HWND_DESKTOP, NULL, pContext->hInstance, pSplashScreen);
280 ExitOnNullWithLastError(pSplashScreen->hWnd, hr, "Failed to create window.");
313 281
314LExit: 282LExit:
283 MemFree(pMonitorContext);
284
315 return hr; 285 return hr;
316} 286}
287
288static BOOL OnDpiChanged(
289 __in SPLASHSCREEN_INFO* pSplashScreen,
290 __in WPARAM wParam,
291 __in LPARAM lParam
292 )
293{
294 UINT nDpi = HIWORD(wParam);
295 RECT* pRect = reinterpret_cast<RECT*>(lParam);
296 BOOL fDpiChanged = pSplashScreen->nDpi != nDpi;
297
298 if (fDpiChanged)
299 {
300 ScaleSplashScreen(pSplashScreen, nDpi, pRect->left, pRect->top);
301 }
302
303 return fDpiChanged;
304}
305
306static void OnEraseBkgnd(
307 __in SPLASHSCREEN_INFO* pSplashScreen,
308 __in WPARAM wParam
309 )
310{
311 HDC hdc = reinterpret_cast<HDC>(wParam);
312 HDC hdcMem = ::CreateCompatibleDC(hdc);
313 HBITMAP hDefaultBitmap = static_cast<HBITMAP>(::SelectObject(hdcMem, pSplashScreen->hBitmap));
314 ::StretchBlt(hdc, 0, 0, pSplashScreen->size.cx, pSplashScreen->size.cy, hdcMem, 0, 0, pSplashScreen->defaultDpiSize.cx, pSplashScreen->defaultDpiSize.cy, SRCCOPY);
315 ::SelectObject(hdcMem, hDefaultBitmap);
316 ::DeleteDC(hdcMem);
317}
318
319static void OnNcCreate(
320 __in HWND hWnd,
321 __in LPARAM lParam
322 )
323{
324 DPIU_WINDOW_CONTEXT windowContext = { };
325 CREATESTRUCTW* pCreateStruct = reinterpret_cast<CREATESTRUCTW*>(lParam);
326 SPLASHSCREEN_INFO* pSplashScreen = reinterpret_cast<SPLASHSCREEN_INFO*>(pCreateStruct->lpCreateParams);
327
328 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pSplashScreen));
329 pSplashScreen->hWnd = hWnd;
330
331 DpiuGetWindowContext(pSplashScreen->hWnd, &windowContext);
332
333 if (windowContext.nDpi != pSplashScreen->nDpi)
334 {
335 ScaleSplashScreen(pSplashScreen, windowContext.nDpi, pCreateStruct->x, pCreateStruct->y);
336 }
337}
338
339static void ScaleSplashScreen(
340 __in SPLASHSCREEN_INFO* pSplashScreen,
341 __in UINT nDpi,
342 __in int x,
343 __in int y
344 )
345{
346 pSplashScreen->nDpi = nDpi;
347
348 pSplashScreen->size.cx = DpiuScaleValue(pSplashScreen->defaultDpiSize.cx, pSplashScreen->nDpi);
349 pSplashScreen->size.cy = DpiuScaleValue(pSplashScreen->defaultDpiSize.cy, pSplashScreen->nDpi);
350
351 if (pSplashScreen->hWnd)
352 {
353 ::SetWindowPos(pSplashScreen->hWnd, NULL, x, y, pSplashScreen->size.cx, pSplashScreen->size.cy, SWP_NOACTIVATE | SWP_NOZORDER);
354 }
355}
diff --git a/src/stub/packages.config b/src/stub/packages.config
index 9aabbf8c..6f98d413 100644
--- a/src/stub/packages.config
+++ b/src/stub/packages.config
@@ -4,5 +4,5 @@
4 <package id="Microsoft.SourceLink.Common" version="1.0.0" targetFramework="native" developmentDependency="true" /> 4 <package id="Microsoft.SourceLink.Common" version="1.0.0" targetFramework="native" developmentDependency="true" />
5 <package id="Microsoft.SourceLink.GitHub" version="1.0.0" targetFramework="native" developmentDependency="true" /> 5 <package id="Microsoft.SourceLink.GitHub" version="1.0.0" targetFramework="native" developmentDependency="true" />
6 <package id="Nerdbank.GitVersioning" version="3.1.91" targetFramework="native" developmentDependency="true" /> 6 <package id="Nerdbank.GitVersioning" version="3.1.91" targetFramework="native" developmentDependency="true" />
7 <package id="WixToolset.DUtil" version="4.0.45" targetFramework="native" /> 7 <package id="WixToolset.DUtil" version="4.0.49" targetFramework="native" />
8</packages> \ No newline at end of file 8</packages> \ No newline at end of file
diff --git a/src/stub/stub.vcxproj b/src/stub/stub.vcxproj
index e0e6c8c6..c0d79f49 100644
--- a/src/stub/stub.vcxproj
+++ b/src/stub/stub.vcxproj
@@ -5,7 +5,7 @@
5 <Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" /> 5 <Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" />
6 <Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props')" /> 6 <Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props')" />
7 <Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props')" /> 7 <Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props')" />
8 <Import Project="..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props')" /> 8 <Import Project="..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props')" />
9 9
10 <ItemGroup Label="ProjectConfigurations"> 10 <ItemGroup Label="ProjectConfigurations">
11 <ProjectConfiguration Include="Debug|Win32"> 11 <ProjectConfiguration Include="Debug|Win32">
@@ -62,7 +62,7 @@
62 <Link> 62 <Link>
63 <SwapRunFromCD>true</SwapRunFromCD> 63 <SwapRunFromCD>true</SwapRunFromCD>
64 <SwapRunFromNET>true</SwapRunFromNET> 64 <SwapRunFromNET>true</SwapRunFromNET>
65 <DelayLoadDLLs>cabinet.dll;crypt32.dll;gdiplus.dll;msi.dll;shlwapi.dll;version.dll;wininet.dll;wintrust.dll</DelayLoadDLLs> 65 <DelayLoadDLLs>cabinet.dll;crypt32.dll;msi.dll;shlwapi.dll;version.dll;wininet.dll;wintrust.dll</DelayLoadDLLs>
66 </Link> 66 </Link>
67 </ItemDefinitionGroup> 67 </ItemDefinitionGroup>
68 68
@@ -107,6 +107,6 @@
107 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props'))" /> 107 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props'))" />
108 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets'))" /> 108 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets'))" />
109 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets'))" /> 109 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.1.91\build\Nerdbank.GitVersioning.targets'))" />
110 <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props'))" /> 110 <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props'))" />
111 </Target> 111 </Target>
112</Project> \ No newline at end of file 112</Project> \ No newline at end of file
diff --git a/src/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/test/BurnUnitTest/BurnUnitTest.vcxproj
index eb2ec4ea..fda7cb7b 100644
--- a/src/test/BurnUnitTest/BurnUnitTest.vcxproj
+++ b/src/test/BurnUnitTest/BurnUnitTest.vcxproj
@@ -4,7 +4,7 @@
4 4
5<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 5<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
6 <Import Project="..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props" Condition="Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props')" /> 6 <Import Project="..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props" Condition="Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props')" />
7 <Import Project="..\..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props" Condition="Exists('..\..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props')" /> 7 <Import Project="..\..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props" Condition="Exists('..\..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props')" />
8 <ItemGroup Label="ProjectConfigurations"> 8 <ItemGroup Label="ProjectConfigurations">
9 <ProjectConfiguration Include="Debug|Win32"> 9 <ProjectConfiguration Include="Debug|Win32">
10 <Configuration>Debug</Configuration> 10 <Configuration>Debug</Configuration>
@@ -28,7 +28,7 @@
28 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 28 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
29 <PropertyGroup> 29 <PropertyGroup>
30 <ProjectAdditionalIncludeDirectories>..\..\engine;..\..\WixToolset.BootstrapperCore.Native\inc</ProjectAdditionalIncludeDirectories> 30 <ProjectAdditionalIncludeDirectories>..\..\engine;..\..\WixToolset.BootstrapperCore.Native\inc</ProjectAdditionalIncludeDirectories>
31 <ProjectAdditionalLinkLibraries>cabinet.lib;crypt32.lib;msi.lib;rpcrt4.lib;shlwapi.lib;wininet.lib;wintrust.lib;gdiplus.lib</ProjectAdditionalLinkLibraries> 31 <ProjectAdditionalLinkLibraries>cabinet.lib;crypt32.lib;msi.lib;rpcrt4.lib;shlwapi.lib;wininet.lib;wintrust.lib</ProjectAdditionalLinkLibraries>
32 </PropertyGroup> 32 </PropertyGroup>
33 <ItemGroup> 33 <ItemGroup>
34 <ClCompile Include="AssemblyInfo.cpp" /> 34 <ClCompile Include="AssemblyInfo.cpp" />
@@ -80,6 +80,6 @@
80 </PropertyGroup> 80 </PropertyGroup>
81 <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props'))" /> 81 <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.props'))" />
82 <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.targets'))" /> 82 <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.40\build\WixBuildTools.TestSupport.Native.targets'))" />
83 <Error Condition="!Exists('..\..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixToolset.DUtil.4.0.45\build\WixToolset.DUtil.props'))" /> 83 <Error Condition="!Exists('..\..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixToolset.DUtil.4.0.49\build\WixToolset.DUtil.props'))" />
84 </Target> 84 </Target>
85</Project> 85</Project>
diff --git a/src/test/BurnUnitTest/packages.config b/src/test/BurnUnitTest/packages.config
index 24bfe34a..e537bcdb 100644
--- a/src/test/BurnUnitTest/packages.config
+++ b/src/test/BurnUnitTest/packages.config
@@ -9,5 +9,5 @@
9 <package id="xunit.runner.visualstudio" version="2.4.1" /> 9 <package id="xunit.runner.visualstudio" version="2.4.1" />
10 <package id="WixBuildTools.TestSupport" version="4.0.40" /> 10 <package id="WixBuildTools.TestSupport" version="4.0.40" />
11 <package id="WixBuildTools.TestSupport.Native" version="4.0.40" /> 11 <package id="WixBuildTools.TestSupport.Native" version="4.0.40" />
12 <package id="WixToolset.DUtil" version="4.0.45" targetFramework="native" /> 12 <package id="WixToolset.DUtil" version="4.0.49" targetFramework="native" />
13</packages> \ No newline at end of file 13</packages> \ No newline at end of file