summaryrefslogtreecommitdiff
path: root/alf/alfcompat.cpp
blob: 269b9f4c98dfb588403e1ba1828ad7c75b131ec7 (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "alfpriv.h"

#include <shlwapi.h>

static
DWORD ALF_DllGetVersion(const char *dll)
{
    HMODULE hDll = GetModuleHandleA(dll);

    if (hDll) {
        DLLGETVERSIONPROC pDllGetVersion;
        pDllGetVersion = (DLLGETVERSIONPROC)(void*)GetProcAddress(hDll, "DllGetVersion");

        if (pDllGetVersion) {
            DLLVERSIONINFO dvi;
            HRESULT hr;

            ZeroMemory(&dvi, sizeof(dvi));
            dvi.cbSize = sizeof(dvi);

            hr = (*pDllGetVersion)(&dvi);

            if (SUCCEEDED(hr)) {
                return MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
            }
        }
    }
    return 0;
}

static int WINAPI
fallbackGetSystemMetricsForDpi(int nIndex, UINT dpi)
{
    (void)dpi;
    return GetSystemMetrics(nIndex);
}

static BOOL WINAPI
fallbackIsAppThemed(void)
{
    return FALSE;
}

static UINT WINAPI
fallbackGetDpiForWindow(HWND win)
{
    (void)win;

    UINT dpi = 0;

    HDC hdcScreen = GetDC(NULL);
    if (hdcScreen) {
        dpi = GetDeviceCaps(hdcScreen, LOGPIXELSY);
        ReleaseDC(NULL, hdcScreen);
    }

    if (!dpi) {
        dpi = 96; // FIXME! fallback to default DPI
    }

    return dpi;
}

static BOOL WINAPI
fallbackSystemParametersInfoForDpi(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi)
{
    (void)dpi;

    return SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
}

static BOOL WINAPI
fallbackAdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi)
{
    (void)dpi;

    return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
}

ALFCompatFunctions *
ALF_CreateCompatFuncTable(void)
{
    ALFCompatFunctions *compatfn = (ALFCompatFunctions*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, sizeof(ALFCompatFunctions));

#define COMPAT(dll, entrypoint, ordinal, fallback) \
    do { \
        FARPROC p = GetProcAddress(GetModuleHandleA(#dll), #entrypoint); \
        if (!p && ordinal) \
            p = GetProcAddress(GetModuleHandleA(#dll), (char*)ordinal); \
        CopyMemory(&compatfn->entrypoint, &p, sizeof(void*)); \
        \
        if (!compatfn->entrypoint) \
            compatfn->entrypoint = fallback; \
    } while (0)

    COMPAT(comctl32.dll, SetWindowSubclass, 410, NULL);
    COMPAT(comctl32.dll, DefSubclassProc, 413, NULL);
    COMPAT(comctl32.dll, RemoveWindowSubclass, 412, NULL);
    COMPAT(user32.dll, GetSystemMetricsForDpi, 0, fallbackGetSystemMetricsForDpi);
    COMPAT(user32.dll, GetDpiForWindow, 0, fallbackGetDpiForWindow);

    // FIXME: SystemParametersInfoForDpi is Unicode-Only.
    // Writing a wrapper function would have been The Right Way, but such a function
    // is yet to be written. So the current practical recommendation is to make
    // ANSI builds System DPI aware only.
#ifdef UNICODE
    COMPAT(user32.dll, SystemParametersInfoForDpi, 0, fallbackSystemParametersInfoForDpi);
#else
    compatfn->SystemParametersInfoForDpi = fallbackSystemParametersInfoForDpi;
#endif

    COMPAT(user32.dll, AdjustWindowRectExForDpi, 0, fallbackAdjustWindowRectExForDpi);

    // IsAppThemed would return TRUE even when we're linked against comctl32 v5
    if (ALF_DllGetVersion("comctl32.dll") >= 0x60000) {
        LoadLibraryA("uxtheme.dll");
        COMPAT(uxtheme.dll, IsAppThemed, 0, fallbackIsAppThemed);
    } else {
        compatfn->IsAppThemed = fallbackIsAppThemed;
    }

#undef COMPAT

    return compatfn;
}

long
ALF_GetAveCharWidth(HDC hdc)
{
    // see: HOWTO: Calculate Dialog Units When Not Using the System Font

    SIZE s;
    GetTextExtentPoint32A(hdc, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &s);

    return (s.cx / 26 + 1) / 2;
}