// Your window's handle
HWND window;
// Get the DPI for which your window should scale to
const UINT dpi{GetDpiForWindow(window)};
// Obtain the recommended fonts, which are already correctly scaled for the current DPI
NONCLIENTMETRICSW non_client_metrics;
non_client_metrics.cbSize = sizeof(non_client_metrics);
if (!SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(non_client_metrics), &non_client_metrics, 0, dpi)
{
// Error handling
}
// Create an appropriate font(s)
HFONT message_font{CreateFontIndirectW(&non_client_metrics.lfMessageFont)};
if (!message_font)
{
// Error handling
}
3条答案
按热度按时间8yparm6h1#
你需要通过
SystemParametersInfo
(SPI_GETNONCLIENTMETRICS
,)得到NONCLIENTMETRICS
,然后使用它的LOGFONT数据,用于创建自己的字体。也可以查询SystemParametersInfo
(SPI_GETICONTITLELOGFONT
)并使用它du7egjpx2#
不同用途的推荐字体可以从
NONCLIENTMETRICS
结构中获得。对于自动DPI缩放的字体(Windows 10 1607+,必须支持每显示器DPI):
字符串
对于较旧的Windows版本,您可以使用系统范围的DPI并手动缩放字体(Windows 7+,必须支持系统DPI):
型
NONCLIENTMETRICS
也有许多其他字体。请确保选择适合您的目的。您应该在application manifest中设置DPI感知级别,如here所述,以获得最佳兼容性。
a0x5cqrl3#
.NET框架中的WinForms内部转换
DEFAULT_GUI_FONT
(实际上在大多数情况下用于获得WinForms Forms和控件的默认字体),通过将其高度从像素(GDI字体本机使用的单位)缩放到Points(GDI+更喜欢)。使用点绘制文本意味着渲染文本的物理大小取决于显示器DPI设置。字符串
显然,你不能直接使用它,因为它是C#。但除此之外,this article建议您应该缩放像素尺寸,假设设计为96 dpi,并使用
GetDpiForWindow
来确定实际的DPI。请注意,上面公式中的“72”与显示器DPI设置无关,它来自于.NET喜欢使用点而不是像素指定的字体(否则只需按DPIy/96缩放LOGFONT的高度)。This site表示类似的东西,但使用
GetDpiForMonitor
。我不能肯定地说,根据一些DPI依赖的因素手动缩放字体大小的一般方法是否是一个强大的和未来的缩放字体(这似乎是去缩放非字体GUI元素的方式)。然而,由于.NET基本上也只是基于某种DPI值计算一些神奇的因子,这可能是一个很好的猜测。
此外,您还需要缓存
HFONT
。HFONT
-LOGFONT
转换不可忽略。参见(参考文献):
WinForms默认使用
GetStockObject(DEFAULT_GUI_FONT)
(但也有一些例外,大部分是过时的):型
https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/SystemFonts.cs,355
HFONT转换为GDI+,然后使用
FontInPoints
转换以这种方式检索的GDI+字体:型
https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/SystemFonts.cs,452
SizeInPoints
getter的内容已经在上面列出了。https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Advanced/Font.cs,992