我需要将字体选择器添加到我的 WPF 文本编辑器中。我正在调整 这个字体选择器。
但是,它列出了所有已安装的字体。我只需要一个固定宽度(等宽)字体的列表。
如何检查给定的 System.Windows.Media.FontFamily 是否是固定宽度字体?
有一个解决方案使用 System.Drawing.FontFamily 但这些字体与 WPF 不完全兼容,我正在改编的代码使用 System.Windows.Media.FontFamily。
也许您可以通过创建同名的 System.Drawing.Font 来过滤 System.Windows.Media.FontFamily 列表,并从那里使用 inteop 和 LOGFONT。
这是一个可怕的黑客,但我相信它在大多数情况下都有效(如果您只使用系统上安装的字体,System.Windows.Media.FontFamily 和 System.Drawing.FontFamily 列表应该大部分匹配)
使用这样的方法来获取字体大小信息或有关高级字体属性的信息将完全无用,因为 WPF 和 GDI 之间的字体渲染器存在差异 - 但对于字体的基本属性(例如固定宽度)我希望这应该可行.
var monoSpacedFonts = Fonts.SystemFontFamilies
.Where(f => f.IsMonoSpace());
有点janky,没有经过彻底测试,但似乎可以使用以下扩展方法:
using System.Globalization;
using System.Windows;
using System.Windows.Media;
namespace StackOverflow;
internal static class ExtensionMethods {
internal static bool IsMonoSpace(this FontFamily @this) {
var result = true;
double? widthComparison = null;
foreach (var typeface in @this.GetTypefaces()) {
foreach (var sample in new char[] { '!', 'W' }) {
var actualWidth = sample.DerivedWidth(typeface);
widthComparison = widthComparison ?? actualWidth;
if (widthComparison != actualWidth) {
result = false;
goto Discontinue;
}
}
}
Discontinue:
return result;
}
internal static double DerivedWidth(this char @this, Typeface typeface, double emSize = 16.0d)
=> new FormattedText(
@this.ToString(),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
emSize,
Brushes.Black
).Width;
}