aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/dpiutil.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-07-06 16:03:23 +1000
committerSean Hall <r.sean.hall@gmail.com>2020-07-06 21:30:49 +1000
commita44cba1e241d0aa7d5c64595e9e7c95d0f06cced (patch)
treea72d182b4d65e7ebd623e04b18ab6db950721cd4 /src/dutil/dpiutil.cpp
parente586152b76d62dbf38cd2882819e23eee2e0af7f (diff)
downloadwix-a44cba1e241d0aa7d5c64595e9e7c95d0f06cced.tar.gz
wix-a44cba1e241d0aa7d5c64595e9e7c95d0f06cced.tar.bz2
wix-a44cba1e241d0aa7d5c64595e9e7c95d0f06cced.zip
Start High-DPI support by scaling the parent window according to the DPI.
Diffstat (limited to 'src/dutil/dpiutil.cpp')
-rw-r--r--src/dutil/dpiutil.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/dutil/dpiutil.cpp b/src/dutil/dpiutil.cpp
new file mode 100644
index 00000000..edab8f01
--- /dev/null
+++ b/src/dutil/dpiutil.cpp
@@ -0,0 +1,117 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5// Exit macros
6#define DpiuExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
7#define DpiuExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
8#define DpiuExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
9#define DpiuExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
10#define DpiuExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
11#define DpiuExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
12#define DpiuExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DPIUTIL, p, x, e, s, __VA_ARGS__)
13#define DpiuExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, p, x, s, __VA_ARGS__)
14#define DpiuExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_DPIUTIL, p, x, e, s, __VA_ARGS__)
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
18static PFN_GETDPIFORMONITOR vpfnGetDpiForMonitor = NULL;
19static PFN_GETDPIFORWINDOW vpfnGetDpiForWindow = NULL;
20
21static HMODULE vhShcoreDll = NULL;
22static HMODULE vhUser32Dll = NULL;
23static BOOL vfDpiuInitialized = FALSE;
24
25DAPI_(void) DpiuInitialize()
26{
27 HRESULT hr = S_OK;
28
29 hr = LoadSystemLibrary(L"Shcore.dll", &vhShcoreDll);
30 if (SUCCEEDED(hr))
31 {
32 // Ignore failures.
33 vpfnGetDpiForMonitor = reinterpret_cast<PFN_GETDPIFORMONITOR>(::GetProcAddress(vhShcoreDll, "GetDpiForMonitor"));
34 }
35
36 hr = LoadSystemLibrary(L"User32.dll", &vhUser32Dll);
37 if (SUCCEEDED(hr))
38 {
39 // Ignore failures.
40 vpfnGetDpiForWindow = reinterpret_cast<PFN_GETDPIFORWINDOW>(::GetProcAddress(vhUser32Dll, "GetDpiForWindow"));
41 }
42
43 vfDpiuInitialized = TRUE;
44}
45
46DAPI_(void) DpiuUninitialize()
47{
48 if (vhShcoreDll)
49 {
50 ::FreeLibrary(vhShcoreDll);
51 }
52
53 if (vhUser32Dll)
54 {
55 ::FreeLibrary(vhUser32Dll);
56 }
57
58 vhShcoreDll = NULL;
59 vhUser32Dll = NULL;
60 vpfnGetDpiForMonitor = NULL;
61 vpfnGetDpiForWindow = NULL;
62 vfDpiuInitialized = FALSE;
63}
64
65DAPI_(void) DpiuGetWindowContext(
66 __in HWND hWnd,
67 __in DPIU_WINDOW_CONTEXT* pWindowContext
68 )
69{
70 HRESULT hr = S_OK;
71 HMONITOR hMonitor = NULL;
72 UINT dpiX = 0;
73 UINT dpiY = 0;
74 HDC hdc = NULL;
75
76 pWindowContext->nDpi = USER_DEFAULT_SCREEN_DPI;
77
78 if (vpfnGetDpiForWindow)
79 {
80 pWindowContext->nDpi = vpfnGetDpiForWindow(hWnd);
81 ExitFunction();
82 }
83
84 if (vpfnGetDpiForMonitor)
85 {
86 hMonitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
87 if (hMonitor)
88 {
89 hr = vpfnGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
90 if (SUCCEEDED(hr))
91 {
92 pWindowContext->nDpi = dpiX;
93 ExitFunction();
94 }
95 }
96 }
97
98 hdc = ::GetDC(hWnd);
99 if (hdc)
100 {
101 pWindowContext->nDpi = ::GetDeviceCaps(hdc, LOGPIXELSX);
102 }
103
104LExit:
105 if (hdc)
106 {
107 ::ReleaseDC(hWnd, hdc);
108 }
109}
110
111DAPI_(int) DpiuScaleValue(
112 __in int nDefaultDpiValue,
113 __in UINT nTargetDpi
114 )
115{
116 return ::MulDiv(nDefaultDpiValue, nTargetDpi, USER_DEFAULT_SCREEN_DPI);
117}