【问题标题】:Stop WPF using Century in place of Century Gothic使用 Century 代替 Century Gothic 停止 WPF
【发布时间】:2011-07-28 09:15:24
【问题描述】:

如果已安装,我们的设计更喜欢使用 Century Gothic,但如果不可用,则回退到 Arial 或 Lucidia。这在大多数情况下都可以正常工作,除非机器没有安装 Century Gothic,但确实有 Century(这似乎是很多没有 Office 的 XP 机器)。 “很有帮助”,它用可怕的衬线字体 Century 代替了 Century Gothic,并且完全忽略了我们的后备字体。

通过使用 Century 而不是 Century Gothic 的机器很容易重现,然后创建一个 TextBlock,例如:

<TextBlock FontFamily="Century Gothic, Wingdings">Should be gibberish</TextBlock>

应该显示为胡言乱语的 Wingdings,但它却显示为丑陋但可读的世纪。

我尝试将 Century Gothic 包装在一种复合字体中,但这也有同样的问题:

<FontFamily
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/composite-font"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:System="clr-namespace:System;assembly=mscorlib">
  <FontFamily.FamilyNames>
    <System:String x:Key="en-US">CenturyGothic</System:String>
  </FontFamily.FamilyNames>
  <FontFamily.FamilyTypefaces>
    <FamilyTypeface Weight="Normal" Stretch="Normal" Style="Normal" />
    <FamilyTypeface Weight="Bold" Stretch="Normal" Style="Normal" />
  </FontFamily.FamilyTypefaces>
  <FontFamily.FamilyMaps>
    <FontFamilyMap Target="Century Gothic" Scale="1" />
  </FontFamily.FamilyMaps>
</FontFamily>

嵌入字体不是一种选择(许可) - 有什么方法可以强制它忽略 Century,还是我只能将其更改为使用不同的字体?

编辑:我刚刚尝试过使用 FontFace="'Century Gothic',Wingdings" 但它永远不会显示 Century Gothic,即使它已安装。

【问题讨论】:

标签: wpf fonts


【解决方案1】:

您可以使用 WPF 样式和合并资源字典来做到这一点。

创建两个资源字典,一个用于默认字体,一个用于备用字体:

DefaultFonts.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="TextBlock">
        <Setter Property="FontFamily" Value="Century Gothic"/>
    </Style>
</ResourceDictionary>

FallbackFonts.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="TextBlock">
        <Setter Property="FontFamily" Value="Arial"/>
    </Style>
</ResourceDictionary>

将这两个文件添加到您的项目中,并将它们的 Build Action 设置为 Resource

将以下代码添加到您的应用启动中:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {            
        base.OnStartup(e);

        string fontsResourcePath = "/DefaultFonts.xaml";
        if (!Fonts.SystemFontFamilies.Any(f => f.FamilyNames.Any(kv => kv.Value == "Century Gothic")))
        {
            fontsResourcePath = "/FallbackFonts.xaml";
        }
        this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri(fontsResourcePath, UriKind.Relative) });
    }
}

这样做会自动在整个应用程序的所有控件上设置正确的字体(除非您在窗口、页面或控件上本地覆盖字体)。

例子:

<Grid>
    <TextBlock>This will show as Century Gothic or fall back to Arial</TextBlock>
</Grid>

编码愉快!

【讨论】:

    【解决方案2】:

    字体的完全限定路径可能会解决问题:

    <TextBlock Margin="20" FontFamily="c:\windows\fonts\GOTHIC.TTF#Century Gothic, Wingdings">Should be gibberish</TextBlock>
    

    硬编码路径并不理想,但您可以添加使用字体友好名称的回退,以防用户通过非标准安装路径运行。您还可以使用代码在注册表中查找字体目录并使用它。

    另一种选择可能是使用代码迭代已安装的字体并以这种方式选择您想要的字体。 System.Windows.Media.Fonts.SystemFontFamilies 已安装字体。找到所需字体后,您可以将该字体系列对象分配给控件,而不是要求它解析字符串。

    【讨论】:

    • 这确实有效,但是通过 windows 目录引用它是一个等待发生的意外(并且 %windir% 不起作用)。
    【解决方案3】:

    问题似乎是 WPF 按 Family 而不是 Face 搜索字体。在您的场景中,Century 和 Century Gothic 都是 Century 字体系列的一部分。因此,您需要将所有面映射到您想要的面。请验证这是否适合您:

    <Label Content="Hello World" FontSize="32">
        <Label.FontFamily>
            <FontFamily xmlns:sys="clr-namespace:System;assembly=mscorlib">
                <FontFamily.FamilyNames>
                    <sys:String x:Key="en-US">Century, Century Gothic, Century Schoolbook</sys:String>
                </FontFamily.FamilyNames>
                <FontFamily.FamilyMaps>
                    <FontFamilyMap Target="Century Gothic" />
    
                    <!-- used when Century Gothic is not available -->
                    <FontFamilyMap Target="Arial" />
                </FontFamily.FamilyMaps>
            </FontFamily>
        </Label.FontFamily>
    </Label>
    

    【讨论】:

    • 啊,有趣,从来没有想过将 Century 添加到字体系列中 - 我已经阅读了关于它如何选择字体的 WPF 论文,它似乎没有提到任何关于假设类似命名的字体是同一个家庭。如果有机会,我今天会试一试。
    • 不幸的是,这不起作用 - 它有完全相同的问题 - 在安装了 Century 而不是 Century Gothic 的机器上,此标签显示为 Century,而不是 Arial。
    • 我在 win xp pro、.net 4 上对其进行了测试,结果符合预期。不知道os和framework版本有影响吗?
    • 根据文档 FontFamily.FamilyNames 是一个带有语言索引的单一姓氏 - 如果您按原样指定它,它代表一种友好名称为“世纪、世纪哥特式、世纪教科书”的字体"
    • 它似乎根本没有使用第二个 FontFamilyMap 条目 - 我已将其更改为 WingDings 并忽略它.. dl.dropbox.com/u/21341/fontproblem/CenturyAndGothic.JPG dl.dropbox.com/u/21341/fontproblem/JustCentury.JPG dl.dropbox.com/u/21341/fontproblem/Neither.JPG gist.github.com/1127620跨度>
    【解决方案4】:

    好的,目前我有一个可行的,如果有点笨拙的感觉,解决方案。我有一个看起来像这样的静态助手类:

    namespace FontFallbackTest
    {
        using System.Linq;
        using System.Windows.Markup;
        using System.Windows.Media;
    
        public static class FontHelper
        {
            private static readonly FontFamily testFont;
            public static FontFamily TestFont
            {
                get
                {
                    return testFont;
                }
            }
    
            static FontHelper()
            {
                testFont = new FontFamily();
    
                testFont.FamilyNames.Add(XmlLanguage.GetLanguage("en-US"), "TestFont");
    
                if (Fonts.SystemFontFamilies.Any(f => f.FamilyNames.Any(kv => kv.Value == "Century Gothic")))
                {
                    testFont.FamilyMaps.Add(new FontFamilyMap() { Target = "Century Gothic" });
                }
    
                testFont.FamilyMaps.Add(new FontFamilyMap() { Target = "Comic Sans MS", Scale = 0.5 });
            }
        }
    }
    

    然后我在我的 XAML 中这样引用:

    <Window x:Class="FontFallbackTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:FontFallbackTest="clr-namespace:FontFallbackTest"
            Title="MainWindow" Height="550" Width="525">
        <Grid>
            <Label Margin="0,100,0,0" FontSize="48" FontFamily="{x:Static FontFallbackTest:FontHelper.TestFont}">This is some text</Label>
            <Label Margin="0,150,0,0" FontSize="48" FontFamily="{x:Static FontFallbackTest:FontHelper.TestFont}">This is more text</Label>
        </Grid>
    </Window>
    

    这似乎有效 - 显示 Century Gothic,忽略 Century,并允许我控制备用字体的缩放。

    【讨论】:

      猜你喜欢
      • 2013-03-29
      • 1970-01-01
      • 2011-01-12
      • 2014-04-10
      • 1970-01-01
      • 2019-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多