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.
26 : m_fInitialized(false)
28 , pfnGetDpiForWindow(nullptr)
29 , pfnGetDpiForSystem(nullptr)
30 , pfnGetSystemMetricsForDpi(nullptr)
31 , pfnSystemParametersInfoForDpi(nullptr)
36 static CDPIAware
& Instance()
38 static CDPIAware instance
;
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
); }
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
);
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
); }
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
)
114 if (pfnSystemParametersInfoForDpi
)
115 ret
= pfnSystemParametersInfoForDpi(uiAction
, uiParam
, pvParam
, fWinIni
, m_dpi
);
117 ret
= ::SystemParametersInfo(uiAction
, uiParam
, pvParam
, fWinIni
);
121 // Invalidate any cached metrics.
122 void Invalidate() { m_fInitialized
= false; }
126 // This function initializes the CDPIAware Class
131 auto hUser
= ::GetModuleHandle(L
"user32.dll");
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();
146 HDC hdc
= GetDC(nullptr);
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
)
167 if (pfnGetSystemMetricsForDpi
)
168 return pfnGetSystemMetricsForDpi(nIndex
, m_dpi
);
169 return MulDiv(::GetSystemMetrics(nIndex
), 96, m_dpi
);
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