WIXFEAT:4906 Make Window's Height and Width refer to its client area.
Sean Hall committed
Jul 6, 2020 at 19:22 UTC
219964095a1f4678d8c8e7ae2685c52392161ca2
5 files changed
+99
-13
src/dutil/dpiutil.cpp
+26
@@ -15,6 +15,7 @@
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_ADJUSTWINDOWRECTEXFORDPI vpfnAdjustWindowRectExForDpi = NULL;
19
static PFN_GETDPIFORMONITOR vpfnGetDpiForMonitor = NULL;
20
static PFN_GETDPIFORWINDOW vpfnGetDpiForWindow = NULL;
21
@@ -37,6 +38,7 @@ DAPI_(void) DpiuInitialize()
38
if (SUCCEEDED(hr))
39
{
40
// Ignore failures.
41
+ vpfnAdjustWindowRectExForDpi = reinterpret_cast<PFN_ADJUSTWINDOWRECTEXFORDPI>(::GetProcAddress(vhUser32Dll, "AdjustWindowRectExForDpi"));
42
vpfnGetDpiForWindow = reinterpret_cast<PFN_GETDPIFORWINDOW>(::GetProcAddress(vhUser32Dll, "GetDpiForWindow"));
43
}
44
@@ -57,11 +59,35 @@ DAPI_(void) DpiuUninitialize()
59
60
vhShcoreDll = NULL;
61
vhUser32Dll = NULL;
62
+ vpfnAdjustWindowRectExForDpi = NULL;
63
vpfnGetDpiForMonitor = NULL;
64
vpfnGetDpiForWindow = NULL;
65
vfDpiuInitialized = FALSE;
66
}
67
68
+DAPI_(void) DpiuAdjustWindowRect(
69
+ __in RECT* pWindowRect,
70
+ __in DWORD dwStyle,
71
+ __in BOOL fMenu,
72
+ __in DWORD dwExStyle,
73
+ __in UINT nDpi
74
+ )
75
+{
76
+ if (WS_SYSMENU & dwStyle)
77
+ {
78
+ dwStyle |= WS_CAPTION; // WS_CAPTION is required with WS_SYSMENU, AdjustWindowRect* won't work properly when it's not specified.
79
+ }
80
+
81
+ if (vpfnAdjustWindowRectExForDpi)
82
+ {
83
+ vpfnAdjustWindowRectExForDpi(pWindowRect, dwStyle, fMenu, dwExStyle, nDpi);
84
+ }
85
+ else
86
+ {
87
+ ::AdjustWindowRectEx(pWindowRect, dwStyle, fMenu, dwExStyle);
88
+ }
89
+}
90
+
91
DAPI_(HRESULT) DpiuGetMonitorContextFromPoint(
92
__in const POINT* pt,
93
__out DPIU_MONITOR_CONTEXT** ppMonitorContext
src/dutil/inc/dpiutil.h
+21
@@ -25,6 +25,13 @@ typedef struct _DPIU_WINDOW_CONTEXT
25
UINT nDpi;
26
} DPIU_WINDOW_CONTEXT;
27
28
+typedef BOOL (APIENTRY* PFN_ADJUSTWINDOWRECTEXFORDPI)(
29
+ __in LPRECT lpRect,
30
+ __in DWORD dwStyle,
31
+ __in BOOL bMenu,
32
+ __in DWORD dwExStyle,
33
+ __in UINT dpi
34
+ );
35
typedef HRESULT (APIENTRY *PFN_GETDPIFORMONITOR)(
36
__in HMONITOR hmonitor,
37
__in MONITOR_DPI_TYPE dpiType,
@@ -38,6 +45,20 @@ typedef UINT (APIENTRY *PFN_GETDPIFORWINDOW)(
45
void DAPI DpiuInitialize();
46
void DAPI DpiuUninitialize();
47
48
+/********************************************************************
49
+ DpiuAdjustWindowRect - calculate the required size of the window rectangle,
50
+ based on the desired size of the client rectangle
51
+ and the provided DPI.
52
+
53
+*******************************************************************/
54
+void DAPI DpiuAdjustWindowRect(
55
+ __in RECT* pWindowRect,
56
+ __in DWORD dwStyle,
57
+ __in BOOL fMenu,
58
+ __in DWORD dwExStyle,
59
+ __in UINT nDpi
60
+ );
61
+
62
/********************************************************************
63
DpiuGetMonitorContextFromPoint - get the DPI context of the monitor from the given point.
64
src/dutil/inc/thmutil.h
+2
@@ -289,6 +289,8 @@ struct THEME
289
int nMinimumHeight;
290
int nWidth;
291
int nMinimumWidth;
292
+ int nWindowHeight;
293
+ int nWindowWidth;
294
int nSourceX;
295
int nSourceY;
296
UINT uStringId;
src/dutil/thmutil.cpp
+48
-11
@@ -367,12 +367,21 @@ static void ResizeControl(
367
__in THEME_CONTROL* pControl,
368
__in const RECT* prcParent
369
);
370
-static void ScaleTheme(
370
+static void ScaleThemeFromWindow(
371
__in THEME* pTheme,
372
__in UINT nDpi,
373
__in int x,
374
__in int y
375
);
376
+static void ScaleTheme(
377
+ __in THEME* pTheme,
378
+ __in UINT nDpi,
379
+ __in int x,
380
+ __in int y,
381
+ __in DWORD dwStyle,
382
+ __in BOOL fMenu,
383
+ __in DWORD dwExStyle
384
+ );
385
static void ScaleControls(
386
__in THEME* pTheme,
387
__in DWORD cControls,
@@ -611,6 +620,7 @@ DAPI_(HRESULT) ThemeCreateParentWindow(
620
DPIU_MONITOR_CONTEXT* pMonitorContext = NULL;
621
POINT pt = { };
622
RECT* pMonitorRect = NULL;
623
+ HMENU hMenu = NULL;
624
HWND hWnd = NULL;
625
626
if (pTheme->hwndParent)
@@ -628,11 +638,11 @@ DAPI_(HRESULT) ThemeCreateParentWindow(
638
pMonitorRect = &pMonitorContext->mi.rcWork;
639
if (pMonitorContext->nDpi != pTheme->nDpi)
640
{
631
- ScaleTheme(pTheme, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top);
641
+ ScaleTheme(pTheme, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top, dwStyle, NULL != hMenu, dwExStyle);
642
}
643
634
- x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pTheme->nWidth) / 2;
635
- y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pTheme->nHeight) / 2;
644
+ x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pTheme->nWindowWidth) / 2;
645
+ y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pTheme->nWindowHeight) / 2;
646
}
647
else
648
{
@@ -641,7 +651,7 @@ DAPI_(HRESULT) ThemeCreateParentWindow(
651
}
652
}
653
644
- hWnd = ::CreateWindowExW(dwExStyle, szClassName, szWindowName, dwStyle, x, y, pTheme->nWidth, pTheme->nHeight, hwndParent, NULL, hInstance, lpParam);
654
+ hWnd = ::CreateWindowExW(dwExStyle, szClassName, szWindowName, dwStyle, x, y, pTheme->nWindowWidth, pTheme->nWindowHeight, hwndParent, hMenu, hInstance, lpParam);
655
ThmExitOnNullWithLastError(hWnd, hr, "Failed to create theme parent window.");
656
ThmExitOnNull(pTheme->hwndParent, hr, E_INVALIDSTATE, "Theme parent window is not set, make sure ThemeDefWindowProc is called for WM_NCCREATE.");
657
AssertSz(hWnd == pTheme->hwndParent, "Theme parent window does not equal newly created window.");
@@ -1909,7 +1919,7 @@ static HRESULT ParseWindow(
1919
}
1920
ThmExitOnFailure(hr, "Failed to get window Width attribute.");
1921
1912
- pTheme->nWidth = pTheme->nDefaultDpiWidth = dwValue;
1922
+ pTheme->nWidth = pTheme->nDefaultDpiWidth = pTheme->nWindowWidth = dwValue;
1923
1924
hr = XmlGetAttributeNumber(pixn, L"Height", &dwValue);
1925
if (S_FALSE == hr)
@@ -1919,7 +1929,7 @@ static HRESULT ParseWindow(
1929
}
1930
ThmExitOnFailure(hr, "Failed to get window Height attribute.");
1931
1922
- pTheme->nHeight = pTheme->nDefaultDpiHeight = dwValue;
1932
+ pTheme->nHeight = pTheme->nDefaultDpiHeight = pTheme->nWindowHeight = dwValue;
1933
1934
hr = XmlGetAttributeNumber(pixn, L"MinimumWidth", &dwValue);
1935
if (S_FALSE == hr)
@@ -4338,7 +4348,7 @@ static BOOL OnDpiChanged(
4348
4349
4350
pTheme->fForceResize = !pTheme->fAutoResize;
4341
- ScaleTheme(pTheme, nDpi, pRect->left, pRect->top);
4351
+ ScaleThemeFromWindow(pTheme, nDpi, pRect->left, pRect->top);
4352
4353
LExit:
4354
return !fIgnored;
@@ -4359,7 +4369,7 @@ static void OnNcCreate(
4369
4370
if (windowContext.nDpi != pTheme->nDpi)
4371
{
4362
- ScaleTheme(pTheme, windowContext.nDpi, pCreateStruct->x, pCreateStruct->y);
4372
+ ScaleTheme(pTheme, windowContext.nDpi, pCreateStruct->x, pCreateStruct->y, pCreateStruct->style, NULL != pCreateStruct->hMenu, pCreateStruct->dwExStyle);
4373
}
4374
}
4375
@@ -5484,13 +5494,32 @@ static void ResizeControl(
5494
}
5495
}
5496
5487
-static void ScaleTheme(
5497
+static void ScaleThemeFromWindow(
5498
__in THEME* pTheme,
5499
__in UINT nDpi,
5500
__in int x,
5501
__in int y
5502
)
5503
{
5504
+ DWORD dwStyle = GetWindowStyle(pTheme->hwndParent);
5505
+ BOOL fMenu = NULL != ::GetMenu(pTheme->hwndParent);
5506
+ DWORD dwExStyle = GetWindowExStyle(pTheme->hwndParent);
5507
+
5508
+ ScaleTheme(pTheme, nDpi, x, y, dwStyle, fMenu, dwExStyle);
5509
+}
5510
+
5511
+static void ScaleTheme(
5512
+ __in THEME* pTheme,
5513
+ __in UINT nDpi,
5514
+ __in int x,
5515
+ __in int y,
5516
+ __in DWORD dwStyle,
5517
+ __in BOOL fMenu,
5518
+ __in DWORD dwExStyle
5519
+ )
5520
+{
5521
+ RECT rect = { };
5522
+
5523
pTheme->nDpi = nDpi;
5524
5525
pTheme->nHeight = DpiuScaleValue(pTheme->nDefaultDpiHeight, pTheme->nDpi);
@@ -5498,11 +5527,19 @@ static void ScaleTheme(
5527
pTheme->nMinimumHeight = DpiuScaleValue(pTheme->nDefaultDpiMinimumHeight, pTheme->nDpi);
5528
pTheme->nMinimumWidth = DpiuScaleValue(pTheme->nDefaultDpiMinimumWidth, pTheme->nDpi);
5529
5530
+ rect.left = x;
5531
+ rect.top = y;
5532
+ rect.right = x + pTheme->nWidth;
5533
+ rect.bottom = y + pTheme->nHeight;
5534
+ DpiuAdjustWindowRect(&rect, dwStyle, fMenu, dwExStyle, pTheme->nDpi);
5535
+ pTheme->nWindowWidth = rect.right - rect.left;
5536
+ pTheme->nWindowHeight = rect.bottom - rect.top;
5537
+
5538
ScaleControls(pTheme, pTheme->cControls, pTheme->rgControls, pTheme->nDpi);
5539
5540
if (pTheme->hwndParent)
5541
{
5505
- ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER);
5542
+ ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWindowWidth, pTheme->nWindowHeight, SWP_NOACTIVATE | SWP_NOZORDER);
5543
}
5544
}
5545
src/dutil/xsd/thmutil.xsd
+2
-2
@@ -165,7 +165,7 @@
165
</xs:attribute>
166
<xs:attribute name="Height" type="xs:positiveInteger" use="required">
167
<xs:annotation>
168
- <xs:documentation>Height of the window.</xs:documentation>
168
+ <xs:documentation>Height of the window's client area.</xs:documentation>
169
</xs:annotation>
170
</xs:attribute>
171
<xs:attribute name="HexStyle" type="xs:hexBinary">
@@ -219,7 +219,7 @@
219
</xs:attribute>
220
<xs:attribute name="Width" type="xs:positiveInteger" use="required">
221
<xs:annotation>
222
- <xs:documentation>Width of the window.</xs:documentation>
222
+ <xs:documentation>Width of the window's client area.</xs:documentation>
223
</xs:annotation>
224
</xs:attribute>
225
</xs:complexType>