From 219964095a1f4678d8c8e7ae2685c52392161ca2 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 6 Jul 2020 19:22:37 +1000 Subject: WIXFEAT:4906 Make Window's Height and Width refer to its client area. --- src/dutil/dpiutil.cpp | 26 +++++++++++++++++++++ src/dutil/inc/dpiutil.h | 21 +++++++++++++++++ src/dutil/inc/thmutil.h | 2 ++ src/dutil/thmutil.cpp | 59 ++++++++++++++++++++++++++++++++++++++--------- src/dutil/xsd/thmutil.xsd | 4 ++-- 5 files changed, 99 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/dutil/dpiutil.cpp b/src/dutil/dpiutil.cpp index a27ee8c5..02a9580c 100644 --- a/src/dutil/dpiutil.cpp +++ b/src/dutil/dpiutil.cpp @@ -15,6 +15,7 @@ #define DpiuExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, p, x, s, __VA_ARGS__) #define DpiuExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_DPIUTIL, e, x, s, __VA_ARGS__) +static PFN_ADJUSTWINDOWRECTEXFORDPI vpfnAdjustWindowRectExForDpi = NULL; static PFN_GETDPIFORMONITOR vpfnGetDpiForMonitor = NULL; static PFN_GETDPIFORWINDOW vpfnGetDpiForWindow = NULL; @@ -37,6 +38,7 @@ DAPI_(void) DpiuInitialize() if (SUCCEEDED(hr)) { // Ignore failures. + vpfnAdjustWindowRectExForDpi = reinterpret_cast(::GetProcAddress(vhUser32Dll, "AdjustWindowRectExForDpi")); vpfnGetDpiForWindow = reinterpret_cast(::GetProcAddress(vhUser32Dll, "GetDpiForWindow")); } @@ -57,11 +59,35 @@ DAPI_(void) DpiuUninitialize() vhShcoreDll = NULL; vhUser32Dll = NULL; + vpfnAdjustWindowRectExForDpi = NULL; vpfnGetDpiForMonitor = NULL; vpfnGetDpiForWindow = NULL; vfDpiuInitialized = FALSE; } +DAPI_(void) DpiuAdjustWindowRect( + __in RECT* pWindowRect, + __in DWORD dwStyle, + __in BOOL fMenu, + __in DWORD dwExStyle, + __in UINT nDpi + ) +{ + if (WS_SYSMENU & dwStyle) + { + dwStyle |= WS_CAPTION; // WS_CAPTION is required with WS_SYSMENU, AdjustWindowRect* won't work properly when it's not specified. + } + + if (vpfnAdjustWindowRectExForDpi) + { + vpfnAdjustWindowRectExForDpi(pWindowRect, dwStyle, fMenu, dwExStyle, nDpi); + } + else + { + ::AdjustWindowRectEx(pWindowRect, dwStyle, fMenu, dwExStyle); + } +} + DAPI_(HRESULT) DpiuGetMonitorContextFromPoint( __in const POINT* pt, __out DPIU_MONITOR_CONTEXT** ppMonitorContext diff --git a/src/dutil/inc/dpiutil.h b/src/dutil/inc/dpiutil.h index 8c61ab19..4ea689c5 100644 --- a/src/dutil/inc/dpiutil.h +++ b/src/dutil/inc/dpiutil.h @@ -25,6 +25,13 @@ typedef struct _DPIU_WINDOW_CONTEXT UINT nDpi; } DPIU_WINDOW_CONTEXT; +typedef BOOL (APIENTRY* PFN_ADJUSTWINDOWRECTEXFORDPI)( + __in LPRECT lpRect, + __in DWORD dwStyle, + __in BOOL bMenu, + __in DWORD dwExStyle, + __in UINT dpi + ); typedef HRESULT (APIENTRY *PFN_GETDPIFORMONITOR)( __in HMONITOR hmonitor, __in MONITOR_DPI_TYPE dpiType, @@ -38,6 +45,20 @@ typedef UINT (APIENTRY *PFN_GETDPIFORWINDOW)( void DAPI DpiuInitialize(); void DAPI DpiuUninitialize(); +/******************************************************************** + DpiuAdjustWindowRect - calculate the required size of the window rectangle, + based on the desired size of the client rectangle + and the provided DPI. + +*******************************************************************/ +void DAPI DpiuAdjustWindowRect( + __in RECT* pWindowRect, + __in DWORD dwStyle, + __in BOOL fMenu, + __in DWORD dwExStyle, + __in UINT nDpi + ); + /******************************************************************** DpiuGetMonitorContextFromPoint - get the DPI context of the monitor from the given point. diff --git a/src/dutil/inc/thmutil.h b/src/dutil/inc/thmutil.h index 1ba5db35..00fa1381 100644 --- a/src/dutil/inc/thmutil.h +++ b/src/dutil/inc/thmutil.h @@ -289,6 +289,8 @@ struct THEME int nMinimumHeight; int nWidth; int nMinimumWidth; + int nWindowHeight; + int nWindowWidth; int nSourceX; int nSourceY; UINT uStringId; diff --git a/src/dutil/thmutil.cpp b/src/dutil/thmutil.cpp index a1b101e8..75b0e4a0 100644 --- a/src/dutil/thmutil.cpp +++ b/src/dutil/thmutil.cpp @@ -367,12 +367,21 @@ static void ResizeControl( __in THEME_CONTROL* pControl, __in const RECT* prcParent ); -static void ScaleTheme( +static void ScaleThemeFromWindow( __in THEME* pTheme, __in UINT nDpi, __in int x, __in int y ); +static void ScaleTheme( + __in THEME* pTheme, + __in UINT nDpi, + __in int x, + __in int y, + __in DWORD dwStyle, + __in BOOL fMenu, + __in DWORD dwExStyle + ); static void ScaleControls( __in THEME* pTheme, __in DWORD cControls, @@ -611,6 +620,7 @@ DAPI_(HRESULT) ThemeCreateParentWindow( DPIU_MONITOR_CONTEXT* pMonitorContext = NULL; POINT pt = { }; RECT* pMonitorRect = NULL; + HMENU hMenu = NULL; HWND hWnd = NULL; if (pTheme->hwndParent) @@ -628,11 +638,11 @@ DAPI_(HRESULT) ThemeCreateParentWindow( pMonitorRect = &pMonitorContext->mi.rcWork; if (pMonitorContext->nDpi != pTheme->nDpi) { - ScaleTheme(pTheme, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top); + ScaleTheme(pTheme, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top, dwStyle, NULL != hMenu, dwExStyle); } - x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pTheme->nWidth) / 2; - y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pTheme->nHeight) / 2; + x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pTheme->nWindowWidth) / 2; + y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pTheme->nWindowHeight) / 2; } else { @@ -641,7 +651,7 @@ DAPI_(HRESULT) ThemeCreateParentWindow( } } - hWnd = ::CreateWindowExW(dwExStyle, szClassName, szWindowName, dwStyle, x, y, pTheme->nWidth, pTheme->nHeight, hwndParent, NULL, hInstance, lpParam); + hWnd = ::CreateWindowExW(dwExStyle, szClassName, szWindowName, dwStyle, x, y, pTheme->nWindowWidth, pTheme->nWindowHeight, hwndParent, hMenu, hInstance, lpParam); ThmExitOnNullWithLastError(hWnd, hr, "Failed to create theme parent window."); ThmExitOnNull(pTheme->hwndParent, hr, E_INVALIDSTATE, "Theme parent window is not set, make sure ThemeDefWindowProc is called for WM_NCCREATE."); AssertSz(hWnd == pTheme->hwndParent, "Theme parent window does not equal newly created window."); @@ -1909,7 +1919,7 @@ static HRESULT ParseWindow( } ThmExitOnFailure(hr, "Failed to get window Width attribute."); - pTheme->nWidth = pTheme->nDefaultDpiWidth = dwValue; + pTheme->nWidth = pTheme->nDefaultDpiWidth = pTheme->nWindowWidth = dwValue; hr = XmlGetAttributeNumber(pixn, L"Height", &dwValue); if (S_FALSE == hr) @@ -1919,7 +1929,7 @@ static HRESULT ParseWindow( } ThmExitOnFailure(hr, "Failed to get window Height attribute."); - pTheme->nHeight = pTheme->nDefaultDpiHeight = dwValue; + pTheme->nHeight = pTheme->nDefaultDpiHeight = pTheme->nWindowHeight = dwValue; hr = XmlGetAttributeNumber(pixn, L"MinimumWidth", &dwValue); if (S_FALSE == hr) @@ -4338,7 +4348,7 @@ static BOOL OnDpiChanged( pTheme->fForceResize = !pTheme->fAutoResize; - ScaleTheme(pTheme, nDpi, pRect->left, pRect->top); + ScaleThemeFromWindow(pTheme, nDpi, pRect->left, pRect->top); LExit: return !fIgnored; @@ -4359,7 +4369,7 @@ static void OnNcCreate( if (windowContext.nDpi != pTheme->nDpi) { - ScaleTheme(pTheme, windowContext.nDpi, pCreateStruct->x, pCreateStruct->y); + ScaleTheme(pTheme, windowContext.nDpi, pCreateStruct->x, pCreateStruct->y, pCreateStruct->style, NULL != pCreateStruct->hMenu, pCreateStruct->dwExStyle); } } @@ -5484,13 +5494,32 @@ static void ResizeControl( } } -static void ScaleTheme( +static void ScaleThemeFromWindow( __in THEME* pTheme, __in UINT nDpi, __in int x, __in int y ) { + DWORD dwStyle = GetWindowStyle(pTheme->hwndParent); + BOOL fMenu = NULL != ::GetMenu(pTheme->hwndParent); + DWORD dwExStyle = GetWindowExStyle(pTheme->hwndParent); + + ScaleTheme(pTheme, nDpi, x, y, dwStyle, fMenu, dwExStyle); +} + +static void ScaleTheme( + __in THEME* pTheme, + __in UINT nDpi, + __in int x, + __in int y, + __in DWORD dwStyle, + __in BOOL fMenu, + __in DWORD dwExStyle + ) +{ + RECT rect = { }; + pTheme->nDpi = nDpi; pTheme->nHeight = DpiuScaleValue(pTheme->nDefaultDpiHeight, pTheme->nDpi); @@ -5498,11 +5527,19 @@ static void ScaleTheme( pTheme->nMinimumHeight = DpiuScaleValue(pTheme->nDefaultDpiMinimumHeight, pTheme->nDpi); pTheme->nMinimumWidth = DpiuScaleValue(pTheme->nDefaultDpiMinimumWidth, pTheme->nDpi); + rect.left = x; + rect.top = y; + rect.right = x + pTheme->nWidth; + rect.bottom = y + pTheme->nHeight; + DpiuAdjustWindowRect(&rect, dwStyle, fMenu, dwExStyle, pTheme->nDpi); + pTheme->nWindowWidth = rect.right - rect.left; + pTheme->nWindowHeight = rect.bottom - rect.top; + ScaleControls(pTheme, pTheme->cControls, pTheme->rgControls, pTheme->nDpi); if (pTheme->hwndParent) { - ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER); + ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWindowWidth, pTheme->nWindowHeight, SWP_NOACTIVATE | SWP_NOZORDER); } } diff --git a/src/dutil/xsd/thmutil.xsd b/src/dutil/xsd/thmutil.xsd index ccf951c0..46c20e4a 100644 --- a/src/dutil/xsd/thmutil.xsd +++ b/src/dutil/xsd/thmutil.xsd @@ -165,7 +165,7 @@ - Height of the window. + Height of the window's client area. @@ -219,7 +219,7 @@ - Width of the window. + Width of the window's client area. -- cgit v1.2.3-55-g6feb