aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-07-06 16:03:23 +1000
committerSean Hall <r.sean.hall@gmail.com>2020-07-06 21:30:49 +1000
commita44cba1e241d0aa7d5c64595e9e7c95d0f06cced (patch)
treea72d182b4d65e7ebd623e04b18ab6db950721cd4
parente586152b76d62dbf38cd2882819e23eee2e0af7f (diff)
downloadwix-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.cpp117
-rw-r--r--src/dutil/dutil.vcxproj2
-rw-r--r--src/dutil/dutil.vcxproj.filters15
-rw-r--r--src/dutil/inc/dpiutil.h55
-rw-r--r--src/dutil/inc/dutilsources.h1
-rw-r--r--src/dutil/inc/thmutil.h6
-rw-r--r--src/dutil/precomp.h2
-rw-r--r--src/dutil/thmutil.cpp90
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
18static PFN_GETDPIFORMONITOR vpfnGetDpiForMonitor = NULL;
19static PFN_GETDPIFORWINDOW vpfnGetDpiForWindow = NULL;
20
21static HMODULE vhShcoreDll = NULL;
22static HMODULE vhUser32Dll = NULL;
23static BOOL vfDpiuInitialized = FALSE;
24
25DAPI_(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
46DAPI_(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
65DAPI_(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
104LExit:
105 if (hdc)
106 {
107 ::ReleaseDC(hWnd, hdc);
108 }
109}
110
111DAPI_(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
6extern "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
17typedef struct _DPIU_WINDOW_CONTEXT
18{
19 UINT nDpi;
20} DPIU_WINDOW_CONTEXT;
21
22typedef HRESULT (APIENTRY *PFN_GETDPIFORMONITOR)(
23 __in HMONITOR hmonitor,
24 __in MONITOR_DPI_TYPE dpiType,
25 __in UINT* dpiX,
26 __in UINT* dpiY
27 );
28typedef UINT (APIENTRY *PFN_GETDPIFORWINDOW)(
29 __in HWND hwnd
30 );
31
32void DAPI DpiuInitialize();
33void DAPI DpiuUninitialize();
34
35/********************************************************************
36 DpiuGetWindowContext - get the DPI context of the given window.
37
38*******************************************************************/
39void 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*******************************************************************/
48int 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 );
290static BOOL OnDpiChanged(
291 __in THEME* pTheme,
292 __in WPARAM wParam,
293 __in LPARAM lParam
294 );
290static void OnNcCreate( 295static 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 );
361static void ScaleTheme(
362 __in THEME* pTheme,
363 __in UINT nDpi,
364 __in int x,
365 __in int y
366 );
356static void GetControls( 367static 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(
4161LExit: 4187LExit:
4162 return fHandled; 4188 return fHandled;
4163} 4189}
4190
4191static 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
4208LExit:
4209 return !fIgnored;
4210}
4164 4211
4165static void OnNcCreate( 4212static 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
4174static HRESULT OnRichEditEnLink( 4231static HRESULT OnRichEditEnLink(
@@ -5282,6 +5339,23 @@ static void ResizeControl(
5282 } 5339 }
5283} 5340}
5284 5341
5342static 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
5285static void UnloadControls( 5359static void UnloadControls(
5286 __in DWORD cControls, 5360 __in DWORD cControls,
5287 __in THEME_CONTROL* rgControls 5361 __in THEME_CONTROL* rgControls