diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2020-07-06 16:03:23 +1000 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2020-07-06 21:30:49 +1000 |
commit | a44cba1e241d0aa7d5c64595e9e7c95d0f06cced (patch) | |
tree | a72d182b4d65e7ebd623e04b18ab6db950721cd4 | |
parent | e586152b76d62dbf38cd2882819e23eee2e0af7f (diff) | |
download | wix-a44cba1e241d0aa7d5c64595e9e7c95d0f06cced.tar.gz wix-a44cba1e241d0aa7d5c64595e9e7c95d0f06cced.tar.bz2 wix-a44cba1e241d0aa7d5c64595e9e7c95d0f06cced.zip |
Start High-DPI support by scaling the parent window according to the DPI.
-rw-r--r-- | src/dutil/dpiutil.cpp | 117 | ||||
-rw-r--r-- | src/dutil/dutil.vcxproj | 2 | ||||
-rw-r--r-- | src/dutil/dutil.vcxproj.filters | 15 | ||||
-rw-r--r-- | src/dutil/inc/dpiutil.h | 55 | ||||
-rw-r--r-- | src/dutil/inc/dutilsources.h | 1 | ||||
-rw-r--r-- | src/dutil/inc/thmutil.h | 6 | ||||
-rw-r--r-- | src/dutil/precomp.h | 2 | ||||
-rw-r--r-- | src/dutil/thmutil.cpp | 90 |
8 files changed, 277 insertions, 11 deletions
diff --git a/src/dutil/dpiutil.cpp b/src/dutil/dpiutil.cpp new file mode 100644 index 00000000..edab8f01 --- /dev/null +++ b/src/dutil/dpiutil.cpp | |||
@@ -0,0 +1,117 @@ | |||
1 | // 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 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | // Exit macros | ||
6 | #define DpiuExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__) | ||
7 | #define DpiuExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__) | ||
8 | #define DpiuExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__) | ||
9 | #define DpiuExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__) | ||
10 | #define DpiuExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__) | ||
11 | #define DpiuExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__) | ||
12 | #define DpiuExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DPIUTIL, p, x, e, s, __VA_ARGS__) | ||
13 | #define DpiuExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, p, x, s, __VA_ARGS__) | ||
14 | #define DpiuExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_DPIUTIL, p, x, e, s, __VA_ARGS__) | ||
15 | #define DpiuExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, p, x, s, __VA_ARGS__) | ||
16 | #define DpiuExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_DPIUTIL, e, x, s, __VA_ARGS__) | ||
17 | |||
18 | static PFN_GETDPIFORMONITOR vpfnGetDpiForMonitor = NULL; | ||
19 | static PFN_GETDPIFORWINDOW vpfnGetDpiForWindow = NULL; | ||
20 | |||
21 | static HMODULE vhShcoreDll = NULL; | ||
22 | static HMODULE vhUser32Dll = NULL; | ||
23 | static BOOL vfDpiuInitialized = FALSE; | ||
24 | |||
25 | DAPI_(void) DpiuInitialize() | ||
26 | { | ||
27 | HRESULT hr = S_OK; | ||
28 | |||
29 | hr = LoadSystemLibrary(L"Shcore.dll", &vhShcoreDll); | ||
30 | if (SUCCEEDED(hr)) | ||
31 | { | ||
32 | // Ignore failures. | ||
33 | vpfnGetDpiForMonitor = reinterpret_cast<PFN_GETDPIFORMONITOR>(::GetProcAddress(vhShcoreDll, "GetDpiForMonitor")); | ||
34 | } | ||
35 | |||
36 | hr = LoadSystemLibrary(L"User32.dll", &vhUser32Dll); | ||
37 | if (SUCCEEDED(hr)) | ||
38 | { | ||
39 | // Ignore failures. | ||
40 | vpfnGetDpiForWindow = reinterpret_cast<PFN_GETDPIFORWINDOW>(::GetProcAddress(vhUser32Dll, "GetDpiForWindow")); | ||
41 | } | ||
42 | |||
43 | vfDpiuInitialized = TRUE; | ||
44 | } | ||
45 | |||
46 | DAPI_(void) DpiuUninitialize() | ||
47 | { | ||
48 | if (vhShcoreDll) | ||
49 | { | ||
50 | ::FreeLibrary(vhShcoreDll); | ||
51 | } | ||
52 | |||
53 | if (vhUser32Dll) | ||
54 | { | ||
55 | ::FreeLibrary(vhUser32Dll); | ||
56 | } | ||
57 | |||
58 | vhShcoreDll = NULL; | ||
59 | vhUser32Dll = NULL; | ||
60 | vpfnGetDpiForMonitor = NULL; | ||
61 | vpfnGetDpiForWindow = NULL; | ||
62 | vfDpiuInitialized = FALSE; | ||
63 | } | ||
64 | |||
65 | DAPI_(void) DpiuGetWindowContext( | ||
66 | __in HWND hWnd, | ||
67 | __in DPIU_WINDOW_CONTEXT* pWindowContext | ||
68 | ) | ||
69 | { | ||
70 | HRESULT hr = S_OK; | ||
71 | HMONITOR hMonitor = NULL; | ||
72 | UINT dpiX = 0; | ||
73 | UINT dpiY = 0; | ||
74 | HDC hdc = NULL; | ||
75 | |||
76 | pWindowContext->nDpi = USER_DEFAULT_SCREEN_DPI; | ||
77 | |||
78 | if (vpfnGetDpiForWindow) | ||
79 | { | ||
80 | pWindowContext->nDpi = vpfnGetDpiForWindow(hWnd); | ||
81 | ExitFunction(); | ||
82 | } | ||
83 | |||
84 | if (vpfnGetDpiForMonitor) | ||
85 | { | ||
86 | hMonitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); | ||
87 | if (hMonitor) | ||
88 | { | ||
89 | hr = vpfnGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); | ||
90 | if (SUCCEEDED(hr)) | ||
91 | { | ||
92 | pWindowContext->nDpi = dpiX; | ||
93 | ExitFunction(); | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | hdc = ::GetDC(hWnd); | ||
99 | if (hdc) | ||
100 | { | ||
101 | pWindowContext->nDpi = ::GetDeviceCaps(hdc, LOGPIXELSX); | ||
102 | } | ||
103 | |||
104 | LExit: | ||
105 | if (hdc) | ||
106 | { | ||
107 | ::ReleaseDC(hWnd, hdc); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | DAPI_(int) DpiuScaleValue( | ||
112 | __in int nDefaultDpiValue, | ||
113 | __in UINT nTargetDpi | ||
114 | ) | ||
115 | { | ||
116 | return ::MulDiv(nDefaultDpiValue, nTargetDpi, USER_DEFAULT_SCREEN_DPI); | ||
117 | } | ||
diff --git a/src/dutil/dutil.vcxproj b/src/dutil/dutil.vcxproj index af8385d1..4bae04d6 100644 --- a/src/dutil/dutil.vcxproj +++ b/src/dutil/dutil.vcxproj | |||
@@ -73,6 +73,7 @@ | |||
73 | <ClCompile Include="dictutil.cpp" /> | 73 | <ClCompile Include="dictutil.cpp" /> |
74 | <ClCompile Include="dirutil.cpp" /> | 74 | <ClCompile Include="dirutil.cpp" /> |
75 | <ClCompile Include="dlutil.cpp" /> | 75 | <ClCompile Include="dlutil.cpp" /> |
76 | <ClCompile Include="dpiutil.cpp" /> | ||
76 | <ClCompile Include="dutil.cpp"> | 77 | <ClCompile Include="dutil.cpp"> |
77 | <PrecompiledHeader>Create</PrecompiledHeader> | 78 | <PrecompiledHeader>Create</PrecompiledHeader> |
78 | <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings> | 79 | <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings> |
@@ -139,6 +140,7 @@ | |||
139 | <ClInclude Include="inc\dictutil.h" /> | 140 | <ClInclude Include="inc\dictutil.h" /> |
140 | <ClInclude Include="inc\dirutil.h" /> | 141 | <ClInclude Include="inc\dirutil.h" /> |
141 | <ClInclude Include="inc\dlutil.h" /> | 142 | <ClInclude Include="inc\dlutil.h" /> |
143 | <ClInclude Include="inc\dpiutil.h" /> | ||
142 | <ClInclude Include="inc\dutil.h" /> | 144 | <ClInclude Include="inc\dutil.h" /> |
143 | <ClInclude Include="inc\dutilsources.h" /> | 145 | <ClInclude Include="inc\dutilsources.h" /> |
144 | <ClInclude Include="inc\eseutil.h" /> | 146 | <ClInclude Include="inc\eseutil.h" /> |
diff --git a/src/dutil/dutil.vcxproj.filters b/src/dutil/dutil.vcxproj.filters index 4dd90fdd..01dd6661 100644 --- a/src/dutil/dutil.vcxproj.filters +++ b/src/dutil/dutil.vcxproj.filters | |||
@@ -60,6 +60,9 @@ | |||
60 | <ClCompile Include="dlutil.cpp"> | 60 | <ClCompile Include="dlutil.cpp"> |
61 | <Filter>Source Files</Filter> | 61 | <Filter>Source Files</Filter> |
62 | </ClCompile> | 62 | </ClCompile> |
63 | <ClCompile Include="dpiutil.cpp"> | ||
64 | <Filter>Source Files</Filter> | ||
65 | </ClCompile> | ||
63 | <ClCompile Include="dutil.cpp"> | 66 | <ClCompile Include="dutil.cpp"> |
64 | <Filter>Source Files</Filter> | 67 | <Filter>Source Files</Filter> |
65 | </ClCompile> | 68 | </ClCompile> |
@@ -230,9 +233,15 @@ | |||
230 | <ClInclude Include="inc\dlutil.h"> | 233 | <ClInclude Include="inc\dlutil.h"> |
231 | <Filter>Header Files</Filter> | 234 | <Filter>Header Files</Filter> |
232 | </ClInclude> | 235 | </ClInclude> |
236 | <ClInclude Include="inc\dpiutil.h"> | ||
237 | <Filter>Header Files</Filter> | ||
238 | </ClInclude> | ||
233 | <ClInclude Include="inc\dutil.h"> | 239 | <ClInclude Include="inc\dutil.h"> |
234 | <Filter>Header Files</Filter> | 240 | <Filter>Header Files</Filter> |
235 | </ClInclude> | 241 | </ClInclude> |
242 | <ClInclude Include="inc\dutilsources.h"> | ||
243 | <Filter>Header Files</Filter> | ||
244 | </ClInclude> | ||
236 | <ClInclude Include="inc\eseutil.h"> | 245 | <ClInclude Include="inc\eseutil.h"> |
237 | <Filter>Header Files</Filter> | 246 | <Filter>Header Files</Filter> |
238 | </ClInclude> | 247 | </ClInclude> |
@@ -287,6 +296,9 @@ | |||
287 | <ClInclude Include="inc\reswutil.h"> | 296 | <ClInclude Include="inc\reswutil.h"> |
288 | <Filter>Header Files</Filter> | 297 | <Filter>Header Files</Filter> |
289 | </ClInclude> | 298 | </ClInclude> |
299 | <ClInclude Include="inc\rmutil.h"> | ||
300 | <Filter>Header Files</Filter> | ||
301 | </ClInclude> | ||
290 | <ClInclude Include="inc\rexutil.h"> | 302 | <ClInclude Include="inc\rexutil.h"> |
291 | <Filter>Header Files</Filter> | 303 | <Filter>Header Files</Filter> |
292 | </ClInclude> | 304 | </ClInclude> |
@@ -344,9 +356,6 @@ | |||
344 | <ClInclude Include="inc\deputil.h"> | 356 | <ClInclude Include="inc\deputil.h"> |
345 | <Filter>Header Files</Filter> | 357 | <Filter>Header Files</Filter> |
346 | </ClInclude> | 358 | </ClInclude> |
347 | <ClInclude Include="inc\dutilsources.h"> | ||
348 | <Filter>Header Files</Filter> | ||
349 | </ClInclude> | ||
350 | </ItemGroup> | 359 | </ItemGroup> |
351 | <ItemGroup> | 360 | <ItemGroup> |
352 | <None Include="xsd\thmutil.xsd"> | 361 | <None Include="xsd\thmutil.xsd"> |
diff --git a/src/dutil/inc/dpiutil.h b/src/dutil/inc/dpiutil.h new file mode 100644 index 00000000..c6f73b02 --- /dev/null +++ b/src/dutil/inc/dpiutil.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #pragma once | ||
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 | |||
4 | |||
5 | #ifdef __cplusplus | ||
6 | extern "C" { | ||
7 | #endif | ||
8 | |||
9 | // from WinUser.h | ||
10 | #ifndef WM_DPICHANGED | ||
11 | #define WM_DPICHANGED 0x02E0 | ||
12 | #endif | ||
13 | #ifndef USER_DEFAULT_SCREEN_DPI | ||
14 | #define USER_DEFAULT_SCREEN_DPI 96 | ||
15 | #endif | ||
16 | |||
17 | typedef struct _DPIU_WINDOW_CONTEXT | ||
18 | { | ||
19 | UINT nDpi; | ||
20 | } DPIU_WINDOW_CONTEXT; | ||
21 | |||
22 | typedef HRESULT (APIENTRY *PFN_GETDPIFORMONITOR)( | ||
23 | __in HMONITOR hmonitor, | ||
24 | __in MONITOR_DPI_TYPE dpiType, | ||
25 | __in UINT* dpiX, | ||
26 | __in UINT* dpiY | ||
27 | ); | ||
28 | typedef UINT (APIENTRY *PFN_GETDPIFORWINDOW)( | ||
29 | __in HWND hwnd | ||
30 | ); | ||
31 | |||
32 | void DAPI DpiuInitialize(); | ||
33 | void DAPI DpiuUninitialize(); | ||
34 | |||
35 | /******************************************************************** | ||
36 | DpiuGetWindowContext - get the DPI context of the given window. | ||
37 | |||
38 | *******************************************************************/ | ||
39 | void DAPI DpiuGetWindowContext( | ||
40 | __in HWND hWnd, | ||
41 | __in DPIU_WINDOW_CONTEXT* pWindowContext | ||
42 | ); | ||
43 | |||
44 | /******************************************************************** | ||
45 | DpiuScaleValue - scale the value to the target DPI. | ||
46 | |||
47 | *******************************************************************/ | ||
48 | int DAPI DpiuScaleValue( | ||
49 | __in int nDefaultDpiValue, | ||
50 | __in UINT nTargetDpi | ||
51 | ); | ||
52 | |||
53 | #ifdef __cplusplus | ||
54 | } | ||
55 | #endif | ||
diff --git a/src/dutil/inc/dutilsources.h b/src/dutil/inc/dutilsources.h index c88ada37..bf3da16f 100644 --- a/src/dutil/inc/dutilsources.h +++ b/src/dutil/inc/dutilsources.h | |||
@@ -19,6 +19,7 @@ typedef enum DUTIL_SOURCE | |||
19 | DUTIL_SOURCE_DICTUTIL, | 19 | DUTIL_SOURCE_DICTUTIL, |
20 | DUTIL_SOURCE_DIRUTIL, | 20 | DUTIL_SOURCE_DIRUTIL, |
21 | DUTIL_SOURCE_DLUTIL, | 21 | DUTIL_SOURCE_DLUTIL, |
22 | DUTIL_SOURCE_DPIUTIL, | ||
22 | DUTIL_SOURCE_DUTIL, | 23 | DUTIL_SOURCE_DUTIL, |
23 | DUTIL_SOURCE_ESEUTIL, | 24 | DUTIL_SOURCE_ESEUTIL, |
24 | DUTIL_SOURCE_FILEUTIL, | 25 | DUTIL_SOURCE_FILEUTIL, |
diff --git a/src/dutil/inc/thmutil.h b/src/dutil/inc/thmutil.h index e661a6cb..52de755f 100644 --- a/src/dutil/inc/thmutil.h +++ b/src/dutil/inc/thmutil.h | |||
@@ -255,6 +255,10 @@ struct THEME | |||
255 | DWORD dwFontId; | 255 | DWORD dwFontId; |
256 | HANDLE hIcon; | 256 | HANDLE hIcon; |
257 | LPWSTR sczCaption; | 257 | LPWSTR sczCaption; |
258 | int nDefaultDpiHeight; | ||
259 | int nDefaultDpiMinimumHeight; | ||
260 | int nDefaultDpiWidth; | ||
261 | int nDefaultDpiMinimumWidth; | ||
258 | int nHeight; | 262 | int nHeight; |
259 | int nMinimumHeight; | 263 | int nMinimumHeight; |
260 | int nWidth; | 264 | int nWidth; |
@@ -283,6 +287,8 @@ struct THEME | |||
283 | DWORD dwCurrentPageId; | 287 | DWORD dwCurrentPageId; |
284 | HWND hwndTooltip; | 288 | HWND hwndTooltip; |
285 | 289 | ||
290 | UINT nDpi; | ||
291 | |||
286 | // callback functions | 292 | // callback functions |
287 | PFNTHM_EVALUATE_VARIABLE_CONDITION pfnEvaluateCondition; | 293 | PFNTHM_EVALUATE_VARIABLE_CONDITION pfnEvaluateCondition; |
288 | PFNTHM_FORMAT_VARIABLE_STRING pfnFormatString; | 294 | PFNTHM_FORMAT_VARIABLE_STRING pfnFormatString; |
diff --git a/src/dutil/precomp.h b/src/dutil/precomp.h index eebdd160..7fdc83ae 100644 --- a/src/dutil/precomp.h +++ b/src/dutil/precomp.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <wuapi.h> | 39 | #include <wuapi.h> |
40 | #include <commctrl.h> | 40 | #include <commctrl.h> |
41 | #include <dbt.h> | 41 | #include <dbt.h> |
42 | #include <ShellScalingApi.h> | ||
42 | 43 | ||
43 | #include "dutilsources.h" | 44 | #include "dutilsources.h" |
44 | #include "dutil.h" | 45 | #include "dutil.h" |
@@ -53,6 +54,7 @@ | |||
53 | #include "eseutil.h" | 54 | #include "eseutil.h" |
54 | #include "dirutil.h" | 55 | #include "dirutil.h" |
55 | #include "dlutil.h" | 56 | #include "dlutil.h" |
57 | #include "dpiutil.h" | ||
56 | #include "fileutil.h" | 58 | #include "fileutil.h" |
57 | #include "guidutil.h" | 59 | #include "guidutil.h" |
58 | #include "gdiputil.h" | 60 | #include "gdiputil.h" |
diff --git a/src/dutil/thmutil.cpp b/src/dutil/thmutil.cpp index 2050b420..4cc149c9 100644 --- a/src/dutil/thmutil.cpp +++ b/src/dutil/thmutil.cpp | |||
@@ -287,6 +287,11 @@ static BOOL OnButtonClicked( | |||
287 | __in HWND hWnd, | 287 | __in HWND hWnd, |
288 | __in const THEME_CONTROL* pControl | 288 | __in const THEME_CONTROL* pControl |
289 | ); | 289 | ); |
290 | static BOOL OnDpiChanged( | ||
291 | __in THEME* pTheme, | ||
292 | __in WPARAM wParam, | ||
293 | __in LPARAM lParam | ||
294 | ); | ||
290 | static void OnNcCreate( | 295 | static void OnNcCreate( |
291 | __in THEME* pTheme, | 296 | __in THEME* pTheme, |
292 | __in HWND hWnd, | 297 | __in HWND hWnd, |
@@ -353,6 +358,12 @@ static void ResizeControl( | |||
353 | __in THEME_CONTROL* pControl, | 358 | __in THEME_CONTROL* pControl, |
354 | __in const RECT* prcParent | 359 | __in const RECT* prcParent |
355 | ); | 360 | ); |
361 | static void ScaleTheme( | ||
362 | __in THEME* pTheme, | ||
363 | __in UINT nDpi, | ||
364 | __in int x, | ||
365 | __in int y | ||
366 | ); | ||
356 | static void GetControls( | 367 | static void GetControls( |
357 | __in THEME* pTheme, | 368 | __in THEME* pTheme, |
358 | __in_opt THEME_CONTROL* pParentControl, | 369 | __in_opt THEME_CONTROL* pParentControl, |
@@ -380,6 +391,8 @@ DAPI_(HRESULT) ThemeInitialize( | |||
380 | HRESULT hr = S_OK; | 391 | HRESULT hr = S_OK; |
381 | INITCOMMONCONTROLSEX icex = { }; | 392 | INITCOMMONCONTROLSEX icex = { }; |
382 | 393 | ||
394 | DpiuInitialize(); | ||
395 | |||
383 | hr = XmlInitialize(); | 396 | hr = XmlInitialize(); |
384 | ThmExitOnFailure(hr, "Failed to initialize XML."); | 397 | ThmExitOnFailure(hr, "Failed to initialize XML."); |
385 | 398 | ||
@@ -430,6 +443,7 @@ DAPI_(void) ThemeUninitialize() | |||
430 | } | 443 | } |
431 | 444 | ||
432 | XmlUninitialize(); | 445 | XmlUninitialize(); |
446 | DpiuUninitialize(); | ||
433 | } | 447 | } |
434 | 448 | ||
435 | 449 | ||
@@ -797,10 +811,10 @@ extern "C" LRESULT CALLBACK ThemeDefWindowProc( | |||
797 | } | 811 | } |
798 | break; | 812 | break; |
799 | 813 | ||
800 | case WM_WINDOWPOSCHANGED: | 814 | case WM_DPICHANGED: |
815 | if (OnDpiChanged(pTheme, wParam, lParam)) | ||
801 | { | 816 | { |
802 | //WINDOWPOS* pos = reinterpret_cast<LPWINDOWPOS>(lParam); | 817 | return 0; |
803 | //ThemeWindowPositionChanged(pTheme, pos); | ||
804 | } | 818 | } |
805 | break; | 819 | break; |
806 | 820 | ||
@@ -1652,6 +1666,7 @@ static HRESULT ParseTheme( | |||
1652 | ThmExitOnNull(pTheme, hr, E_OUTOFMEMORY, "Failed to allocate memory for theme."); | 1666 | ThmExitOnNull(pTheme, hr, E_OUTOFMEMORY, "Failed to allocate memory for theme."); |
1653 | 1667 | ||
1654 | pTheme->wId = ++wThemeId; | 1668 | pTheme->wId = ++wThemeId; |
1669 | pTheme->nDpi = USER_DEFAULT_SCREEN_DPI; | ||
1655 | 1670 | ||
1656 | // Parse the optional background resource image. | 1671 | // Parse the optional background resource image. |
1657 | hr = ParseImage(hModule, wzRelativePath, pThemeElement, &pTheme->hImage); | 1672 | hr = ParseImage(hModule, wzRelativePath, pThemeElement, &pTheme->hImage); |
@@ -1816,6 +1831,7 @@ static HRESULT ParseWindow( | |||
1816 | { | 1831 | { |
1817 | HRESULT hr = S_OK; | 1832 | HRESULT hr = S_OK; |
1818 | IXMLDOMNode* pixn = NULL; | 1833 | IXMLDOMNode* pixn = NULL; |
1834 | DWORD dwValue = 0; | ||
1819 | BSTR bstr = NULL; | 1835 | BSTR bstr = NULL; |
1820 | LPWSTR sczIconFile = NULL; | 1836 | LPWSTR sczIconFile = NULL; |
1821 | 1837 | ||
@@ -1833,7 +1849,7 @@ static HRESULT ParseWindow( | |||
1833 | } | 1849 | } |
1834 | ThmExitOnFailure(hr, "Failed to get window AutoResize attribute."); | 1850 | ThmExitOnFailure(hr, "Failed to get window AutoResize attribute."); |
1835 | 1851 | ||
1836 | hr = XmlGetAttributeNumber(pixn, L"Width", reinterpret_cast<DWORD*>(&pTheme->nWidth)); | 1852 | hr = XmlGetAttributeNumber(pixn, L"Width", &dwValue); |
1837 | if (S_FALSE == hr) | 1853 | if (S_FALSE == hr) |
1838 | { | 1854 | { |
1839 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); | 1855 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); |
@@ -1841,7 +1857,9 @@ static HRESULT ParseWindow( | |||
1841 | } | 1857 | } |
1842 | ThmExitOnFailure(hr, "Failed to get window Width attribute."); | 1858 | ThmExitOnFailure(hr, "Failed to get window Width attribute."); |
1843 | 1859 | ||
1844 | hr = XmlGetAttributeNumber(pixn, L"Height", reinterpret_cast<DWORD*>(&pTheme->nHeight)); | 1860 | pTheme->nWidth = pTheme->nDefaultDpiWidth = dwValue; |
1861 | |||
1862 | hr = XmlGetAttributeNumber(pixn, L"Height", &dwValue); | ||
1845 | if (S_FALSE == hr) | 1863 | if (S_FALSE == hr) |
1846 | { | 1864 | { |
1847 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); | 1865 | hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); |
@@ -1849,20 +1867,28 @@ static HRESULT ParseWindow( | |||
1849 | } | 1867 | } |
1850 | ThmExitOnFailure(hr, "Failed to get window Height attribute."); | 1868 | ThmExitOnFailure(hr, "Failed to get window Height attribute."); |
1851 | 1869 | ||
1852 | hr = XmlGetAttributeNumber(pixn, L"MinimumWidth", reinterpret_cast<DWORD*>(&pTheme->nMinimumWidth)); | 1870 | pTheme->nHeight = pTheme->nDefaultDpiHeight = dwValue; |
1871 | |||
1872 | hr = XmlGetAttributeNumber(pixn, L"MinimumWidth", &dwValue); | ||
1853 | if (S_FALSE == hr) | 1873 | if (S_FALSE == hr) |
1854 | { | 1874 | { |
1875 | dwValue = 0; | ||
1855 | hr = S_OK; | 1876 | hr = S_OK; |
1856 | } | 1877 | } |
1857 | ThmExitOnFailure(hr, "Failed to get window MinimumWidth attribute."); | 1878 | ThmExitOnFailure(hr, "Failed to get window MinimumWidth attribute."); |
1858 | 1879 | ||
1859 | hr = XmlGetAttributeNumber(pixn, L"MinimumHeight", reinterpret_cast<DWORD*>(&pTheme->nMinimumHeight)); | 1880 | pTheme->nMinimumWidth = pTheme->nDefaultDpiMinimumWidth = dwValue; |
1881 | |||
1882 | hr = XmlGetAttributeNumber(pixn, L"MinimumHeight", &dwValue); | ||
1860 | if (S_FALSE == hr) | 1883 | if (S_FALSE == hr) |
1861 | { | 1884 | { |
1885 | dwValue = 0; | ||
1862 | hr = S_OK; | 1886 | hr = S_OK; |
1863 | } | 1887 | } |
1864 | ThmExitOnFailure(hr, "Failed to get window MinimumHeight attribute."); | 1888 | ThmExitOnFailure(hr, "Failed to get window MinimumHeight attribute."); |
1865 | 1889 | ||
1890 | pTheme->nMinimumHeight = pTheme->nDefaultDpiMinimumHeight = dwValue; | ||
1891 | |||
1866 | hr = XmlGetAttributeNumber(pixn, L"FontId", &pTheme->dwFontId); | 1892 | hr = XmlGetAttributeNumber(pixn, L"FontId", &pTheme->dwFontId); |
1867 | if (S_FALSE == hr) | 1893 | if (S_FALSE == hr) |
1868 | { | 1894 | { |
@@ -4161,14 +4187,45 @@ static BOOL OnButtonClicked( | |||
4161 | LExit: | 4187 | LExit: |
4162 | return fHandled; | 4188 | return fHandled; |
4163 | } | 4189 | } |
4190 | |||
4191 | static BOOL OnDpiChanged( | ||
4192 | __in THEME* pTheme, | ||
4193 | __in WPARAM wParam, | ||
4194 | __in LPARAM lParam | ||
4195 | ) | ||
4196 | { | ||
4197 | UINT nDpi = HIWORD(wParam); | ||
4198 | RECT* pRect = reinterpret_cast<RECT*>(lParam); | ||
4199 | BOOL fIgnored = pTheme->nDpi == nDpi; | ||
4200 | |||
4201 | if (fIgnored) | ||
4202 | { | ||
4203 | ExitFunction(); | ||
4204 | } | ||
4205 | |||
4206 | ScaleTheme(pTheme, nDpi, pRect->left, pRect->top); | ||
4207 | |||
4208 | LExit: | ||
4209 | return !fIgnored; | ||
4210 | } | ||
4164 | 4211 | ||
4165 | static void OnNcCreate( | 4212 | static void OnNcCreate( |
4166 | __in THEME* pTheme, | 4213 | __in THEME* pTheme, |
4167 | __in HWND hWnd, | 4214 | __in HWND hWnd, |
4168 | __in LPARAM /*lParam*/ | 4215 | __in LPARAM lParam |
4169 | ) | 4216 | ) |
4170 | { | 4217 | { |
4218 | DPIU_WINDOW_CONTEXT windowContext = { }; | ||
4219 | CREATESTRUCTW* pCreateStruct = reinterpret_cast<CREATESTRUCTW*>(lParam); | ||
4220 | |||
4171 | pTheme->hwndParent = hWnd; | 4221 | pTheme->hwndParent = hWnd; |
4222 | |||
4223 | DpiuGetWindowContext(pTheme->hwndParent, &windowContext); | ||
4224 | |||
4225 | if (windowContext.nDpi != pTheme->nDpi) | ||
4226 | { | ||
4227 | ScaleTheme(pTheme, windowContext.nDpi, pCreateStruct->x, pCreateStruct->y); | ||
4228 | } | ||
4172 | } | 4229 | } |
4173 | 4230 | ||
4174 | static HRESULT OnRichEditEnLink( | 4231 | static HRESULT OnRichEditEnLink( |
@@ -5282,6 +5339,23 @@ static void ResizeControl( | |||
5282 | } | 5339 | } |
5283 | } | 5340 | } |
5284 | 5341 | ||
5342 | static void ScaleTheme( | ||
5343 | __in THEME* pTheme, | ||
5344 | __in UINT nDpi, | ||
5345 | __in int x, | ||
5346 | __in int y | ||
5347 | ) | ||
5348 | { | ||
5349 | pTheme->nDpi = nDpi; | ||
5350 | |||
5351 | pTheme->nHeight = DpiuScaleValue(pTheme->nDefaultDpiHeight, pTheme->nDpi); | ||
5352 | pTheme->nWidth = DpiuScaleValue(pTheme->nDefaultDpiWidth, pTheme->nDpi); | ||
5353 | pTheme->nMinimumHeight = DpiuScaleValue(pTheme->nDefaultDpiMinimumHeight, pTheme->nDpi); | ||
5354 | pTheme->nMinimumWidth = DpiuScaleValue(pTheme->nDefaultDpiMinimumWidth, pTheme->nDpi); | ||
5355 | |||
5356 | ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER); | ||
5357 | } | ||
5358 | |||
5285 | static void UnloadControls( | 5359 | static void UnloadControls( |
5286 | __in DWORD cControls, | 5360 | __in DWORD cControls, |
5287 | __in THEME_CONTROL* rgControls | 5361 | __in THEME_CONTROL* rgControls |