带有 gdi+ 的 PrivateFontCollection 有时会在 WIndows 8 或更高版本中使用错误的 FontStyle
PrivateFontCollection with gdi+ sometimes uses the wrong FontStyle in WIndows 8 or newer
如果您有一个从 PrivateFontCollection 创建的字体并尝试使用 GDI+ 用它绘制字符串,它有时会使用错误的 FontStyle。
我观察到这一点,字体从内存加载到 PrivateFontCollection 中,字体从文件加载到 PrivateFontCollection 中。
在下面的示例中,我从文件中加载字体。我把它们都放在一个名为 Fonts 的文件夹中。如果我们像下面这样加载它们。
private void loadFontsIntoPrivateCollection()
{
_privateFontCollection = new PrivateFontCollection();
_families = new Dictionary<string, FontFamily>();
var files = Directory.GetFiles("Fonts");
foreach (var file in files)
_privateFontCollection.AddFontFile(file);
foreach (var fontFamily in _privateFontCollection.Families)
{
_families.Add(fontFamily.Name, fontFamily);
comboBox1.Items.Add(fontFamily.Name);
}
comboBox1.Text = "Californian FB";
}
然后尝试使用以下代码绘制字符串 OnPaint
private void panelTextArea_Paint(object sender, PaintEventArgs e)
{
var familyToUse = _families[comboBox1.Text];
var fontToUse = new Font(familyToUse, 28, _styleToUse, GraphicsUnit.World);
e.Graphics.DrawString(textBox1.Text, fontToUse, Brushes.Black, panelTextArea.ClientRectangle);
}
那么字符串在大多数情况下会被绘制成FontStyle.Regular对应的字体。我注意到,如果您首先注意加载常规字体,那么 FontFamily 将伪造 FontStyle.Regular 以外的任何 FontStyle。无论您是否已将它们加载到 PrivateFontCollection 中。
以下是我在其中看到此行为的一些字体。
- 于哥特式
- 加州 FB
- Tw岑山
- Gill Sans MT
- Berlin Sans FB
- BrowalliaUPC
- 繁体阿拉伯语
我在 graphicsPath 上执行 Graphics.DrawString() 和 AddString 时看到了这种行为。使用 TextRenderer.DrawText() 将正确绘制字体。
您应该能够在 Windows 8 或 10 中轻松地重新创建此行为,只需使用他们的 PrivateFontCollection 示例代码 https://msdn.microsoft.com/en-us/library/windows/desktop/ms533820(v=vs.85).aspx
根据我与微软就此行为的通信,他们认为这是 gdi+ 的问题。
我们注意到,如果您只将一个 FontStyle 加载到 PrivateFontCollection 中,它将始终使用该 FontStyle。
我们所做的是包装 PrivateFontCollection 和 FontFamily classes 所以当我们从文件加载字体到我们的 PrivateFontCollection 时,它实际上将它添加到 4 个 PrivateFontCollections 之一,具体取决于字体的 FontStyle文件有。
然后我们通过调用我们自己的 FontFamily class 创建字体,它具有从适当的 PrivateFontCollection select 字体的逻辑。
如果您有一个从 PrivateFontCollection 创建的字体并尝试使用 GDI+ 用它绘制字符串,它有时会使用错误的 FontStyle。
我观察到这一点,字体从内存加载到 PrivateFontCollection 中,字体从文件加载到 PrivateFontCollection 中。
在下面的示例中,我从文件中加载字体。我把它们都放在一个名为 Fonts 的文件夹中。如果我们像下面这样加载它们。
private void loadFontsIntoPrivateCollection()
{
_privateFontCollection = new PrivateFontCollection();
_families = new Dictionary<string, FontFamily>();
var files = Directory.GetFiles("Fonts");
foreach (var file in files)
_privateFontCollection.AddFontFile(file);
foreach (var fontFamily in _privateFontCollection.Families)
{
_families.Add(fontFamily.Name, fontFamily);
comboBox1.Items.Add(fontFamily.Name);
}
comboBox1.Text = "Californian FB";
}
然后尝试使用以下代码绘制字符串 OnPaint
private void panelTextArea_Paint(object sender, PaintEventArgs e)
{
var familyToUse = _families[comboBox1.Text];
var fontToUse = new Font(familyToUse, 28, _styleToUse, GraphicsUnit.World);
e.Graphics.DrawString(textBox1.Text, fontToUse, Brushes.Black, panelTextArea.ClientRectangle);
}
那么字符串在大多数情况下会被绘制成FontStyle.Regular对应的字体。我注意到,如果您首先注意加载常规字体,那么 FontFamily 将伪造 FontStyle.Regular 以外的任何 FontStyle。无论您是否已将它们加载到 PrivateFontCollection 中。
以下是我在其中看到此行为的一些字体。
- 于哥特式
- 加州 FB
- Tw岑山
- Gill Sans MT
- Berlin Sans FB
- BrowalliaUPC
- 繁体阿拉伯语
我在 graphicsPath 上执行 Graphics.DrawString() 和 AddString 时看到了这种行为。使用 TextRenderer.DrawText() 将正确绘制字体。
您应该能够在 Windows 8 或 10 中轻松地重新创建此行为,只需使用他们的 PrivateFontCollection 示例代码 https://msdn.microsoft.com/en-us/library/windows/desktop/ms533820(v=vs.85).aspx
根据我与微软就此行为的通信,他们认为这是 gdi+ 的问题。
我们注意到,如果您只将一个 FontStyle 加载到 PrivateFontCollection 中,它将始终使用该 FontStyle。
我们所做的是包装 PrivateFontCollection 和 FontFamily classes 所以当我们从文件加载字体到我们的 PrivateFontCollection 时,它实际上将它添加到 4 个 PrivateFontCollections 之一,具体取决于字体的 FontStyle文件有。
然后我们通过调用我们自己的 FontFamily class 创建字体,它具有从适当的 PrivateFontCollection select 字体的逻辑。