.NET 框架中的 WinForms 在内部转换 DEFAULT_GUI_FONT(实际上在大多数情况下用于获取 WinForms 窗体和控件的默认字体)通过从像素缩放其高度(这是 GDI 字体本机使用的单位) ) 到点(这是 GDI+ 的首选)。使用点绘制文本意味着渲染文本的物理大小取决于显示器 DPI 设置。
System.Drawing.Font.SizeInPoints:
float emHeightInPoints;
IntPtr screenDC = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef);
try {
using( Graphics graphics = Graphics.FromHdcInternal(screenDC)){
float pixelsPerPoint = (float) (graphics.DpiY / 72.0);
float lineSpacingInPixels = this.GetHeight(graphics);
float emHeightInPixels = lineSpacingInPixels * FontFamily.GetEmHeight(Style) / FontFamily.GetLineSpacing(Style);
emHeightInPoints = emHeightInPixels / pixelsPerPoint;
}
}
finally {
UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, screenDC));
}
return emHeightInPoints;
显然你不能直接使用它,因为它是 C#。但除此之外,this article 建议您应该在假设 96 dpi 设计的情况下缩放像素尺寸,并使用GetDpiForWindow 来确定实际 DPI。请注意,上面公式中的“72”与显示器 DPI 设置无关,这是因为 .NET 喜欢使用以点而不是像素指定的字体(否则只需将 LOGFONT 的高度缩放 DPIy/96) .
This site 提出了类似的建议,但使用了GetDpiForMonitor。
我不能确定根据某些 DPI 相关因素手动缩放字体大小的一般方法是否是缩放字体的可靠且面向未来的方法(这似乎是缩放非字体 GUI 的方法元素虽然)。但是,由于 .NET 基本上也只是根据某种 DPI 值计算一些魔法因子,所以这可能是一个不错的猜测。
此外,您还需要缓存 HFONT。 HFONT - LOGFONT 转换不可忽略。
另见(参考):
WinForms 使用GetStockObject(DEFAULT_GUI_FONT) 获取其默认值(不过也有一些例外,大部分已过时):
IntPtr handle = UnsafeNativeMethods.GetStockObject(NativeMethods.DEFAULT_GUI_FONT);
try {
Font fontInWorldUnits = null;
// SECREVIEW : We know that we got the handle from the stock object,
// : so this is always safe.
//
IntSecurity.ObjectFromWin32Handle.Assert();
try {
fontInWorldUnits = Font.FromHfont(handle);
}
finally {
CodeAccessPermission.RevertAssert();
}
try{
defaultFont = FontInPoints(fontInWorldUnits);
}
finally{
fontInWorldUnits.Dispose();
}
}
catch (ArgumentException) {
}
https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/SystemFonts.cs,355
HFONT转换成GDI+,然后用FontInPoints转换这种方式检索到的GDI+字体:
private static Font FontInPoints(Font font) {
return new Font(font.FontFamily, font.SizeInPoints, font.Style, GraphicsUnit.Point, font.GdiCharSet, font.GdiVerticalFont);
}
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