CPatch: New memory management
[TortoiseGit.git] / src / Utils / DPIAware.h
blob4c0150494a166fb2e673467bb424fa9bbaf00ff7
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2018 - TortoiseGit
4 // Copyright (C) 2018 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
22 class CDPIAware
24 private:
25 CDPIAware()
26 : m_fInitialized(false)
27 , m_dpi(96)
28 , pfnGetDpiForWindow(nullptr)
29 , pfnGetDpiForSystem(nullptr)
30 , pfnGetSystemMetricsForDpi(nullptr)
31 , pfnSystemParametersInfoForDpi(nullptr)
33 ~CDPIAware() {}
35 public:
36 static CDPIAware& Instance()
38 static CDPIAware instance;
39 return instance;
42 private:
43 // Get screen DPI.
44 int GetDPI() { _Init(); return m_dpi; }
46 // Convert between raw pixels and relative pixels.
47 int Scale(int x) { _Init(); return MulDiv(x, m_dpi, 96); }
48 float ScaleFactor() { _Init(); return m_dpi / 96.0f; }
49 int Unscale(int x) { _Init(); return MulDiv(x, 96, m_dpi); }
50 public:
51 inline int GetDPIX() { return GetDPI(); }
52 inline int GetDPIY() { return GetDPI(); }
53 inline int ScaleX(int x) { return Scale(x); }
54 inline int ScaleY(int y) { return Scale(y); }
55 inline float ScaleFactorX() { return ScaleFactor(); }
56 inline float ScaleFactorY() { return ScaleFactor(); }
57 inline int UnscaleX(int x) { return Unscale(x); }
58 inline int UnscaleY(int y) { return Unscale(y); }
59 inline int PointsToPixelsX(int pt) { return PointsToPixels(pt); }
60 inline int PointsToPixelsY(int pt) { return PointsToPixels(pt); }
61 inline int PixelsToPointsX(int px) { return PixelsToPoints(px); }
62 inline int PixelsToPointsY(int px) { return PixelsToPoints(px); }
64 // Determine the screen dimensions in relative pixels.
65 int ScaledScreenWidth() { return _ScaledSystemMetric(SM_CXSCREEN); }
66 int ScaledScreenHeight() { return _ScaledSystemMetric(SM_CYSCREEN); }
68 // Scale rectangle from raw pixels to relative pixels.
69 void ScaleRect(__inout RECT *pRect)
71 pRect->left = Scale(pRect->left);
72 pRect->right = Scale(pRect->right);
73 pRect->top = Scale(pRect->top);
74 pRect->bottom = Scale(pRect->bottom);
77 // Scale Point from raw pixels to relative pixels.
78 void ScalePoint(__inout POINT *pPoint)
80 pPoint->x = Scale(pPoint->x);
81 pPoint->y = Scale(pPoint->y);
84 // Scale Size from raw pixels to relative pixels.
85 void ScaleSize(__inout SIZE *pSize)
87 pSize->cx = Scale(pSize->cx);
88 pSize->cy = Scale(pSize->cy);
91 // Determine if screen resolution meets minimum requirements in relative pixels.
92 bool IsResolutionAtLeast(int cxMin, int cyMin)
94 return (ScaledScreenWidth() >= cxMin) && (ScaledScreenHeight() >= cyMin);
97 private:
98 // Convert a point size (1/72 of an inch) to raw pixels.
99 int PointsToPixels(int pt) { _Init(); return MulDiv(pt, m_dpi, 72); }
100 int PixelsToPoints(int px) { _Init(); return MulDiv(px, 72, m_dpi); }
102 public:
103 // returns the system metrics. For Windows 10, it returns the metrics dpi scaled.
104 UINT GetSystemMetrics(int nIndex)
106 return _ScaledSystemMetric(nIndex);
109 // returns the system parameters info. If possible adjusted for dpi.
110 UINT SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
112 _Init();
113 UINT ret = 0;
114 if (pfnSystemParametersInfoForDpi)
115 ret = pfnSystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, m_dpi);
116 if (ret == 0)
117 ret = ::SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
118 return ret;
121 // Invalidate any cached metrics.
122 void Invalidate() { m_fInitialized = false; }
124 private:
126 // This function initializes the CDPIAware Class
127 void _Init()
129 if (!m_fInitialized)
131 auto hUser = ::GetModuleHandle(L"user32.dll");
132 if (hUser)
134 pfnGetDpiForWindow = (GetDpiForWindowFN*)GetProcAddress(hUser, "GetDpiForWindow");
135 pfnGetDpiForSystem = (GetDpiForSystemFN*)GetProcAddress(hUser, "GetDpiForSystem");
136 pfnGetSystemMetricsForDpi = (GetSystemMetricsForDpiFN*)GetProcAddress(hUser, "GetSystemMetricsForDpi");
137 pfnSystemParametersInfoForDpi = (SystemParametersInfoForDpiFN*)GetProcAddress(hUser, "SystemParametersInfoForDpi");
140 if (pfnGetDpiForSystem)
142 m_dpi = pfnGetDpiForSystem();
144 else
146 HDC hdc = GetDC(nullptr);
147 if (hdc)
149 // Initialize the DPI member variable
150 // This will correspond to the DPI setting
151 // With all Windows OS's to date the X and Y DPI will be identical
152 m_dpi = GetDeviceCaps(hdc, LOGPIXELSX);
153 ReleaseDC(nullptr, hdc);
156 m_fInitialized = true;
160 // This returns a 96-DPI scaled-down equivalent value for nIndex
161 // For example, the value 120 at 120 DPI setting gets scaled down to 96
162 // X and Y versions are provided, though to date all Windows OS releases
163 // have equal X and Y scale values
164 int _ScaledSystemMetric(int nIndex)
166 _Init();
167 if (pfnGetSystemMetricsForDpi)
168 return pfnGetSystemMetricsForDpi(nIndex, m_dpi);
169 return MulDiv(::GetSystemMetrics(nIndex), 96, m_dpi);
172 private:
173 typedef UINT STDAPICALLTYPE GetDpiForWindowFN(HWND hWnd);
174 typedef UINT STDAPICALLTYPE GetDpiForSystemFN();
175 typedef UINT STDAPICALLTYPE GetSystemMetricsForDpiFN(int nIndex, UINT dpi);
176 typedef UINT STDAPICALLTYPE SystemParametersInfoForDpiFN(UINT uiAction,UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi);
178 GetDpiForWindowFN* pfnGetDpiForWindow;
179 GetDpiForSystemFN* pfnGetDpiForSystem;
180 GetSystemMetricsForDpiFN* pfnGetSystemMetricsForDpi;
181 SystemParametersInfoForDpiFN* pfnSystemParametersInfoForDpi;
183 // Member variable indicating whether the class has been initialized
184 bool m_fInitialized;
186 int m_dpi;