From abeba64d77336b3fbf9aafe9ecc66b779c1e5d02 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 6 Jul 2020 16:22:38 +1000 Subject: Add ability for ThemeCreateParentWindow to center on the monitor. --- src/dutil/dpiutil.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dutil/inc/dpiutil.h | 15 ++++++++++++++ src/dutil/inc/thmutil.h | 7 +++++++ src/dutil/thmutil.cpp | 34 ++++++++++++++++++++++++++++++- 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/dutil/dpiutil.cpp b/src/dutil/dpiutil.cpp index edab8f01..a27ee8c5 100644 --- a/src/dutil/dpiutil.cpp +++ b/src/dutil/dpiutil.cpp @@ -62,6 +62,59 @@ DAPI_(void) DpiuUninitialize() vfDpiuInitialized = FALSE; } +DAPI_(HRESULT) DpiuGetMonitorContextFromPoint( + __in const POINT* pt, + __out DPIU_MONITOR_CONTEXT** ppMonitorContext + ) +{ + HRESULT hr = S_OK; + DPIU_MONITOR_CONTEXT* pMonitorContext = NULL; + HMONITOR hMonitor = NULL; + UINT dpiX = 0; + UINT dpiY = 0; + HDC hdc = NULL; + + pMonitorContext = reinterpret_cast(MemAlloc(sizeof(DPIU_MONITOR_CONTEXT), TRUE)); + DpiuExitOnNull(pMonitorContext, hr, E_OUTOFMEMORY, "Failed to allocate memory for DpiuMonitorContext."); + + hMonitor = ::MonitorFromPoint(*pt, MONITOR_DEFAULTTONEAREST); + DpiuExitOnNull(hMonitor, hr, E_FAIL, "Failed to get monitor from point."); + + pMonitorContext->mi.cbSize = sizeof(pMonitorContext->mi); + if (!::GetMonitorInfoW(hMonitor, &pMonitorContext->mi)) + { + DpiuExitOnFailure(hr = E_OUTOFMEMORY, "Failed to get monitor info for point."); + } + + if (vpfnGetDpiForMonitor) + { + hr = vpfnGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + DpiuExitOnFailure(hr, "Failed to get DPI for monitor."); + + pMonitorContext->nDpi = dpiX; + } + else + { + hdc = ::CreateDCW(L"DISPLAY", pMonitorContext->mi.szDevice, NULL, NULL); + DpiuExitOnNull(hdc, hr, E_OUTOFMEMORY, "Failed to get device context for monitor."); + + pMonitorContext->nDpi = ::GetDeviceCaps(hdc, LOGPIXELSX); + } + + *ppMonitorContext = pMonitorContext; + pMonitorContext = NULL; + +LExit: + if (hdc) + { + ::ReleaseDC(NULL, hdc); + } + + MemFree(pMonitorContext); + + return hr; +} + DAPI_(void) DpiuGetWindowContext( __in HWND hWnd, __in DPIU_WINDOW_CONTEXT* pWindowContext diff --git a/src/dutil/inc/dpiutil.h b/src/dutil/inc/dpiutil.h index c6f73b02..8c61ab19 100644 --- a/src/dutil/inc/dpiutil.h +++ b/src/dutil/inc/dpiutil.h @@ -14,6 +14,12 @@ extern "C" { #define USER_DEFAULT_SCREEN_DPI 96 #endif +typedef struct _DPIU_MONITOR_CONTEXT +{ + UINT nDpi; + MONITORINFOEXW mi; +} DPIU_MONITOR_CONTEXT; + typedef struct _DPIU_WINDOW_CONTEXT { UINT nDpi; @@ -32,6 +38,15 @@ typedef UINT (APIENTRY *PFN_GETDPIFORWINDOW)( void DAPI DpiuInitialize(); void DAPI DpiuUninitialize(); +/******************************************************************** + DpiuGetMonitorContextFromPoint - get the DPI context of the monitor from the given point. + +*******************************************************************/ +HRESULT DAPI DpiuGetMonitorContextFromPoint( + __in const POINT* pt, + __out DPIU_MONITOR_CONTEXT** ppMonitorContext + ); + /******************************************************************** DpiuGetWindowContext - get the DPI context of the given window. diff --git a/src/dutil/inc/thmutil.h b/src/dutil/inc/thmutil.h index c75f9587..1ba5db35 100644 --- a/src/dutil/inc/thmutil.h +++ b/src/dutil/inc/thmutil.h @@ -81,6 +81,12 @@ typedef enum THEME_SHOW_PAGE_REASON THEME_SHOW_PAGE_REASON_REFRESH, } THEME_SHOW_PAGE_REASON; +typedef enum THEME_WINDOW_INITIAL_POSITION +{ + THEME_WINDOW_INITIAL_POSITION_DEFAULT, + THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES, +} THEME_WINDOW_INITIAL_POSITION; + struct THEME_COLUMN { @@ -394,6 +400,7 @@ HRESULT DAPI ThemeCreateParentWindow( __in_opt HWND hwndParent, __in_opt HINSTANCE hInstance, __in_opt LPVOID lpParam, + __in THEME_WINDOW_INITIAL_POSITION initialPosition, __out_opt HWND* phWnd ); diff --git a/src/dutil/thmutil.cpp b/src/dutil/thmutil.cpp index 4da489e4..a1b101e8 100644 --- a/src/dutil/thmutil.cpp +++ b/src/dutil/thmutil.cpp @@ -603,10 +603,14 @@ DAPI_(HRESULT) ThemeCreateParentWindow( __in_opt HWND hwndParent, __in_opt HINSTANCE hInstance, __in_opt LPVOID lpParam, + __in THEME_WINDOW_INITIAL_POSITION initialPosition, __out_opt HWND* phWnd ) { HRESULT hr = S_OK; + DPIU_MONITOR_CONTEXT* pMonitorContext = NULL; + POINT pt = { }; + RECT* pMonitorRect = NULL; HWND hWnd = NULL; if (pTheme->hwndParent) @@ -614,6 +618,29 @@ DAPI_(HRESULT) ThemeCreateParentWindow( ThmExitOnFailure(hr = E_INVALIDSTATE, "ThemeCreateParentWindow called after the theme was loaded."); } + if (THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES == initialPosition) + { + pt.x = x; + pt.y = y; + hr = DpiuGetMonitorContextFromPoint(&pt, &pMonitorContext); + if (SUCCEEDED(hr)) + { + pMonitorRect = &pMonitorContext->mi.rcWork; + if (pMonitorContext->nDpi != pTheme->nDpi) + { + ScaleTheme(pTheme, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top); + } + + x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pTheme->nWidth) / 2; + y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pTheme->nHeight) / 2; + } + else + { + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + } + } + hWnd = ::CreateWindowExW(dwExStyle, szClassName, szWindowName, dwStyle, x, y, pTheme->nWidth, pTheme->nHeight, hwndParent, NULL, 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."); @@ -625,6 +652,8 @@ DAPI_(HRESULT) ThemeCreateParentWindow( } LExit: + MemFree(pMonitorContext); + return hr; } @@ -5471,7 +5500,10 @@ static void ScaleTheme( ScaleControls(pTheme, pTheme->cControls, pTheme->rgControls, pTheme->nDpi); - ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER); + if (pTheme->hwndParent) + { + ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER); + } } static void ScaleControls( -- cgit v1.2.3-55-g6feb