@joebigelow / wix / commits / 21996409

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>