aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/dpiutil.cpp
blob: edab8f019ad04fcb72a771fb245c16b4160cdfae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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.

#include "precomp.h"

// Exit macros
#define DpiuExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
#define DpiuExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
#define DpiuExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
#define DpiuExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
#define DpiuExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
#define DpiuExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_DPIUTIL, x, s, __VA_ARGS__)
#define DpiuExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_DPIUTIL, p, x, e, s, __VA_ARGS__)
#define DpiuExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_DPIUTIL, p, x, s, __VA_ARGS__)
#define DpiuExitOnNullDebugTrace(p, x, e, s, ...)  ExitOnNullDebugTraceSource(DUTIL_SOURCE_DPIUTIL, p, x, e, s, __VA_ARGS__)
#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_GETDPIFORMONITOR vpfnGetDpiForMonitor = NULL;
static PFN_GETDPIFORWINDOW vpfnGetDpiForWindow = NULL;

static HMODULE vhShcoreDll = NULL;
static HMODULE vhUser32Dll = NULL;
static BOOL vfDpiuInitialized = FALSE;

DAPI_(void) DpiuInitialize()
{
    HRESULT hr = S_OK;

    hr = LoadSystemLibrary(L"Shcore.dll", &vhShcoreDll);
    if (SUCCEEDED(hr))
    {
        // Ignore failures.
        vpfnGetDpiForMonitor = reinterpret_cast<PFN_GETDPIFORMONITOR>(::GetProcAddress(vhShcoreDll, "GetDpiForMonitor"));
    }

    hr = LoadSystemLibrary(L"User32.dll", &vhUser32Dll);
    if (SUCCEEDED(hr))
    {
        // Ignore failures.
        vpfnGetDpiForWindow = reinterpret_cast<PFN_GETDPIFORWINDOW>(::GetProcAddress(vhUser32Dll, "GetDpiForWindow"));
    }

    vfDpiuInitialized = TRUE;
}

DAPI_(void) DpiuUninitialize()
{
    if (vhShcoreDll)
    {
        ::FreeLibrary(vhShcoreDll);
    }

    if (vhUser32Dll)
    {
        ::FreeLibrary(vhUser32Dll);
    }

    vhShcoreDll = NULL;
    vhUser32Dll = NULL;
    vpfnGetDpiForMonitor = NULL;
    vpfnGetDpiForWindow = NULL;
    vfDpiuInitialized = FALSE;
}

DAPI_(void) DpiuGetWindowContext(
    __in HWND hWnd,
    __in DPIU_WINDOW_CONTEXT* pWindowContext
    )
{
    HRESULT hr = S_OK;
    HMONITOR hMonitor = NULL;
    UINT dpiX = 0;
    UINT dpiY = 0;
    HDC hdc = NULL;

    pWindowContext->nDpi = USER_DEFAULT_SCREEN_DPI;

    if (vpfnGetDpiForWindow)
    {
        pWindowContext->nDpi = vpfnGetDpiForWindow(hWnd);
        ExitFunction();
    }

    if (vpfnGetDpiForMonitor)
    {
        hMonitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
        if (hMonitor)
        {
            hr = vpfnGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
            if (SUCCEEDED(hr))
            {
                pWindowContext->nDpi = dpiX;
                ExitFunction();
            }
        }
    }

    hdc = ::GetDC(hWnd);
    if (hdc)
    {
        pWindowContext->nDpi = ::GetDeviceCaps(hdc, LOGPIXELSX);
    }

LExit:
    if (hdc)
    {
        ::ReleaseDC(hWnd, hdc);
    }
}

DAPI_(int) DpiuScaleValue(
    __in int nDefaultDpiValue,
    __in UINT nTargetDpi
    )
{
    return ::MulDiv(nDefaultDpiValue, nTargetDpi, USER_DEFAULT_SCREEN_DPI);
}