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(