1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2018 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 : m_fInitialized(false)
27 , pfnGetDpiForWindow(nullptr)
28 , pfnGetDpiForSystem(nullptr)
29 , pfnGetSystemMetricsForDpi(nullptr)
30 , pfnSystemParametersInfoForDpi(nullptr)
35 static CDPIAware
& Instance()
37 static CDPIAware instance
;
43 int GetDPI() { _Init(); return m_dpi
; }
45 // Convert between raw pixels and relative pixels.
46 int Scale(int x
) { _Init(); return MulDiv(x
, m_dpi
, 96); }
47 float ScaleFactor() { _Init(); return m_dpi
/ 96.0f
; }
48 int Unscale(int x
) { _Init(); return MulDiv(x
, 96, m_dpi
); }
50 inline int GetDPIX() { return GetDPI(); }
51 inline int GetDPIY() { return GetDPI(); }
52 inline int ScaleX(int x
) { return Scale(x
); }
53 inline int ScaleY(int y
) { return Scale(y
); }
54 inline float ScaleFactorX() { return ScaleFactor(); }
55 inline float ScaleFactorY() { return ScaleFactor(); }
56 inline int UnscaleX(int x
) { return Unscale(x
); }
57 inline int UnscaleY(int y
) { return Unscale(y
); }
58 inline int PointsToPixelsX(int pt
) { return PointsToPixels(pt
); }
59 inline int PointsToPixelsY(int pt
) { return PointsToPixels(pt
); }
61 // Determine the screen dimensions in relative pixels.
62 int ScaledScreenWidth() { return _ScaledSystemMetric(SM_CXSCREEN
); }
63 int ScaledScreenHeight() { return _ScaledSystemMetric(SM_CYSCREEN
); }
65 // Scale rectangle from raw pixels to relative pixels.
66 void ScaleRect(__inout RECT
*pRect
)
68 pRect
->left
= Scale(pRect
->left
);
69 pRect
->right
= Scale(pRect
->right
);
70 pRect
->top
= Scale(pRect
->top
);
71 pRect
->bottom
= Scale(pRect
->bottom
);
74 // Scale Point from raw pixels to relative pixels.
75 void ScalePoint(__inout POINT
*pPoint
)
77 pPoint
->x
= Scale(pPoint
->x
);
78 pPoint
->y
= Scale(pPoint
->y
);
81 // Scale Size from raw pixels to relative pixels.
82 void ScaleSize(__inout SIZE
*pSize
)
84 pSize
->cx
= Scale(pSize
->cx
);
85 pSize
->cy
= Scale(pSize
->cy
);
88 // Determine if screen resolution meets minimum requirements in relative pixels.
89 bool IsResolutionAtLeast(int cxMin
, int cyMin
)
91 return (ScaledScreenWidth() >= cxMin
) && (ScaledScreenHeight() >= cyMin
);
95 // Convert a point size (1/72 of an inch) to raw pixels.
96 int PointsToPixels(int pt
) { _Init(); return MulDiv(pt
, m_dpi
, 72); }
99 // returns the system metrics. For Windows 10, it returns the metrics dpi scaled.
100 UINT
GetSystemMetrics(int nIndex
)
102 return _ScaledSystemMetric(nIndex
);
105 // returns the system parameters info. If possible adjusted for dpi.
106 UINT
SystemParametersInfo(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
110 if (pfnSystemParametersInfoForDpi
)
111 ret
= pfnSystemParametersInfoForDpi(uiAction
, uiParam
, pvParam
, fWinIni
, m_dpi
);
113 ret
= ::SystemParametersInfo(uiAction
, uiParam
, pvParam
, fWinIni
);
117 // Invalidate any cached metrics.
118 void Invalidate() { m_fInitialized
= false; }
122 // This function initializes the CDPIAware Class
127 auto hUser
= ::GetModuleHandle(L
"user32.dll");
130 pfnGetDpiForWindow
= (GetDpiForWindowFN
*)GetProcAddress(hUser
, "GetDpiForWindow");
131 pfnGetDpiForSystem
= (GetDpiForSystemFN
*)GetProcAddress(hUser
, "GetDpiForSystem");
132 pfnGetSystemMetricsForDpi
= (GetSystemMetricsForDpiFN
*)GetProcAddress(hUser
, "GetSystemMetricsForDpi");
133 pfnSystemParametersInfoForDpi
= (SystemParametersInfoForDpiFN
*)GetProcAddress(hUser
, "SystemParametersInfoForDpi");
136 if (pfnGetDpiForSystem
)
138 m_dpi
= pfnGetDpiForSystem();
142 HDC hdc
= GetDC(nullptr);
145 // Initialize the DPI member variable
146 // This will correspond to the DPI setting
147 // With all Windows OS's to date the X and Y DPI will be identical
148 m_dpi
= GetDeviceCaps(hdc
, LOGPIXELSX
);
149 ReleaseDC(nullptr, hdc
);
152 m_fInitialized
= true;
156 // This returns a 96-DPI scaled-down equivalent value for nIndex
157 // For example, the value 120 at 120 DPI setting gets scaled down to 96
158 // X and Y versions are provided, though to date all Windows OS releases
159 // have equal X and Y scale values
160 int _ScaledSystemMetric(int nIndex
)
163 if (pfnGetSystemMetricsForDpi
)
164 return pfnGetSystemMetricsForDpi(nIndex
, m_dpi
);
165 return MulDiv(::GetSystemMetrics(nIndex
), 96, m_dpi
);
169 typedef UINT STDAPICALLTYPE
GetDpiForWindowFN(HWND hWnd
);
170 typedef UINT STDAPICALLTYPE
GetDpiForSystemFN();
171 typedef UINT STDAPICALLTYPE
GetSystemMetricsForDpiFN(int nIndex
, UINT dpi
);
172 typedef UINT STDAPICALLTYPE
SystemParametersInfoForDpiFN(UINT uiAction
,UINT uiParam
, PVOID pvParam
, UINT fWinIni
, UINT dpi
);
174 GetDpiForWindowFN
* pfnGetDpiForWindow
;
175 GetDpiForSystemFN
* pfnGetDpiForSystem
;
176 GetSystemMetricsForDpiFN
* pfnGetSystemMetricsForDpi
;
177 SystemParametersInfoForDpiFN
* pfnSystemParametersInfoForDpi
;
179 // Member variable indicating whether the class has been initialized