@joebigelow / wix / commits / abeba64d

Add ability for ThemeCreateParentWindow to center on the monitor.

Sean Hall committed Jul 6, 2020 at 16:22 UTC abeba64d77336b3fbf9aafe9ecc66b779c1e5d02
4 files changed +108 -1
src/dutil/dpiutil.cpp
+53
@@ -62,6 +62,59 @@ DAPI_(void) DpiuUninitialize()
62 vfDpiuInitialized = FALSE;
63 }
64
65 +DAPI_(HRESULT) DpiuGetMonitorContextFromPoint(
66 + __in const POINT* pt,
67 + __out DPIU_MONITOR_CONTEXT** ppMonitorContext
68 + )
69 +{
70 + HRESULT hr = S_OK;
71 + DPIU_MONITOR_CONTEXT* pMonitorContext = NULL;
72 + HMONITOR hMonitor = NULL;
73 + UINT dpiX = 0;
74 + UINT dpiY = 0;
75 + HDC hdc = NULL;
76 +
77 + pMonitorContext = reinterpret_cast<DPIU_MONITOR_CONTEXT*>(MemAlloc(sizeof(DPIU_MONITOR_CONTEXT), TRUE));
78 + DpiuExitOnNull(pMonitorContext, hr, E_OUTOFMEMORY, "Failed to allocate memory for DpiuMonitorContext.");
79 +
80 + hMonitor = ::MonitorFromPoint(*pt, MONITOR_DEFAULTTONEAREST);
81 + DpiuExitOnNull(hMonitor, hr, E_FAIL, "Failed to get monitor from point.");
82 +
83 + pMonitorContext->mi.cbSize = sizeof(pMonitorContext->mi);
84 + if (!::GetMonitorInfoW(hMonitor, &pMonitorContext->mi))
85 + {
86 + DpiuExitOnFailure(hr = E_OUTOFMEMORY, "Failed to get monitor info for point.");
87 + }
88 +
89 + if (vpfnGetDpiForMonitor)
90 + {
91 + hr = vpfnGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
92 + DpiuExitOnFailure(hr, "Failed to get DPI for monitor.");
93 +
94 + pMonitorContext->nDpi = dpiX;
95 + }
96 + else
97 + {
98 + hdc = ::CreateDCW(L"DISPLAY", pMonitorContext->mi.szDevice, NULL, NULL);
99 + DpiuExitOnNull(hdc, hr, E_OUTOFMEMORY, "Failed to get device context for monitor.");
100 +
101 + pMonitorContext->nDpi = ::GetDeviceCaps(hdc, LOGPIXELSX);
102 + }
103 +
104 + *ppMonitorContext = pMonitorContext;
105 + pMonitorContext = NULL;
106 +
107 +LExit:
108 + if (hdc)
109 + {
110 + ::ReleaseDC(NULL, hdc);
111 + }
112 +
113 + MemFree(pMonitorContext);
114 +
115 + return hr;
116 +}
117 +
118 DAPI_(void) DpiuGetWindowContext(
119 __in HWND hWnd,
120 __in DPIU_WINDOW_CONTEXT* pWindowContext
src/dutil/inc/dpiutil.h
+15
@@ -14,6 +14,12 @@ extern "C" {
14 #define USER_DEFAULT_SCREEN_DPI 96
15 #endif
16
17 +typedef struct _DPIU_MONITOR_CONTEXT
18 +{
19 + UINT nDpi;
20 + MONITORINFOEXW mi;
21 +} DPIU_MONITOR_CONTEXT;
22 +
23 typedef struct _DPIU_WINDOW_CONTEXT
24 {
25 UINT nDpi;
@@ -32,6 +38,15 @@ typedef UINT (APIENTRY *PFN_GETDPIFORWINDOW)(
38 void DAPI DpiuInitialize();
39 void DAPI DpiuUninitialize();
40
41 +/********************************************************************
42 + DpiuGetMonitorContextFromPoint - get the DPI context of the monitor from the given point.
43 +
44 +*******************************************************************/
45 +HRESULT DAPI DpiuGetMonitorContextFromPoint(
46 + __in const POINT* pt,
47 + __out DPIU_MONITOR_CONTEXT** ppMonitorContext
48 + );
49 +
50 /********************************************************************
51 DpiuGetWindowContext - get the DPI context of the given window.
52
src/dutil/inc/thmutil.h
+7
@@ -81,6 +81,12 @@ typedef enum THEME_SHOW_PAGE_REASON
81 THEME_SHOW_PAGE_REASON_REFRESH,
82 } THEME_SHOW_PAGE_REASON;
83
84 +typedef enum THEME_WINDOW_INITIAL_POSITION
85 +{
86 + THEME_WINDOW_INITIAL_POSITION_DEFAULT,
87 + THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES,
88 +} THEME_WINDOW_INITIAL_POSITION;
89 +
90
91 struct THEME_COLUMN
92 {
@@ -394,6 +400,7 @@ HRESULT DAPI ThemeCreateParentWindow(
400 __in_opt HWND hwndParent,
401 __in_opt HINSTANCE hInstance,
402 __in_opt LPVOID lpParam,
403 + __in THEME_WINDOW_INITIAL_POSITION initialPosition,
404 __out_opt HWND* phWnd
405 );
406
src/dutil/thmutil.cpp
+33 -1
@@ -603,10 +603,14 @@ DAPI_(HRESULT) ThemeCreateParentWindow(
603 __in_opt HWND hwndParent,
604 __in_opt HINSTANCE hInstance,
605 __in_opt LPVOID lpParam,
606 + __in THEME_WINDOW_INITIAL_POSITION initialPosition,
607 __out_opt HWND* phWnd
608 )
609 {
610 HRESULT hr = S_OK;
611 + DPIU_MONITOR_CONTEXT* pMonitorContext = NULL;
612 + POINT pt = { };
613 + RECT* pMonitorRect = NULL;
614 HWND hWnd = NULL;
615
616 if (pTheme->hwndParent)
@@ -614,6 +618,29 @@ DAPI_(HRESULT) ThemeCreateParentWindow(
618 ThmExitOnFailure(hr = E_INVALIDSTATE, "ThemeCreateParentWindow called after the theme was loaded.");
619 }
620
621 + if (THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES == initialPosition)
622 + {
623 + pt.x = x;
624 + pt.y = y;
625 + hr = DpiuGetMonitorContextFromPoint(&pt, &pMonitorContext);
626 + if (SUCCEEDED(hr))
627 + {
628 + pMonitorRect = &pMonitorContext->mi.rcWork;
629 + if (pMonitorContext->nDpi != pTheme->nDpi)
630 + {
631 + ScaleTheme(pTheme, pMonitorContext->nDpi, pMonitorRect->left, pMonitorRect->top);
632 + }
633 +
634 + x = pMonitorRect->left + (pMonitorRect->right - pMonitorRect->left - pTheme->nWidth) / 2;
635 + y = pMonitorRect->top + (pMonitorRect->bottom - pMonitorRect->top - pTheme->nHeight) / 2;
636 + }
637 + else
638 + {
639 + x = CW_USEDEFAULT;
640 + y = CW_USEDEFAULT;
641 + }
642 + }
643 +
644 hWnd = ::CreateWindowExW(dwExStyle, szClassName, szWindowName, dwStyle, x, y, pTheme->nWidth, pTheme->nHeight, hwndParent, NULL, hInstance, lpParam);
645 ThmExitOnNullWithLastError(hWnd, hr, "Failed to create theme parent window.");
646 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(
652 }
653
654 LExit:
655 + MemFree(pMonitorContext);
656 +
657 return hr;
658 }
659
@@ -5471,7 +5500,10 @@ static void ScaleTheme(
5500
5501 ScaleControls(pTheme, pTheme->cControls, pTheme->rgControls, pTheme->nDpi);
5502
5474 - ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER);
5503 + if (pTheme->hwndParent)
5504 + {
5505 + ::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER);
5506 + }
5507 }
5508
5509 static void ScaleControls(