65.9K
CodeProject 正在变化。 阅读更多。
Home

使用字体图标

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2013年8月9日

CPOL

2分钟阅读

viewsIcon

69758

downloadIcon

2996

此技巧帮助将字体图标用作ImageSource。

引言

此技巧提供了一种在大多数WPF控件(如Ribbon)中使用字体图标的解决方案。

背景

我最近在WPF应用程序中使用Ribbon时遇到一个问题。问题是Ribbon只允许使用ImageSource显示图标。我的目标是使用字体图标库(如HTML中那样),因为它包含矢量图标,并且最终应用程序是同质的。

在示例中,您将找到字体

Using the Code

  1. 创建一个新的WPF项目(可以是MVVM)。
  2. 创建一个Ribbon(添加对System.Windows.Controls.Ribbon的引用)。
  3. 嵌入包含可缩放图标的字体
    1. 从您的Resource.resx中添加ttf文件
    2. 在解决方案资源管理器中,找到TTF文件并将“生成操作”更改为“资源”
  4. 添加对WpfTools的引用(在下载包中)
  5. 将字体图标用作ImageSource

要显示字体中的图标

<RibbonButton Label="Import data" 
  LargeImageSource="{WpfTools:ImageFromFont Text=&#xf01a;, 
  FontFamily=/RibbonFontIconSample;component/Resources/#FontAwesome, Brush=Brown}" /> 

使用以下参数

  • Text:表示图标的字符(取决于字体。对于FontAwesome,我使用速查表http://fortawesome.github.io/Font-Awesome/cheatsheet/获取代码。
  • FontFamily用于选择嵌入式字体(使用以下语法)
  • Brush用于为图标着色(可以是Colorstatic资源)
  • Style用于斜体
  • Weight用于粗体

关注点

此类可用于任何具有ImageSource属性的控件(RibbonImage等)。

这是一种在应用程序中拥有高清图标的方法,因为它们是可缩放的矢量图标。

工作原理

由于无法重写ImageSource,因此解决方案之一是创建一个MarkupExtension

MarkupExtension是一个可在XAML代码中{ }内使用的类,并且只有一个纯abstract方法ProvideValue,该方法用于获取结果对象。

public override object ProvideValue(IServiceProvider serviceProvider)
{
    return CreateGlyph(Text, FontFamily, Style, Weight, Stretch, Brush);
}   

在WPF中,将string呈现为可绘制对象的一种方法是使用Glyph(和GlyphRun)。

glyph是一种以标量方式渲染一个或多个字符的方法。它使用字体和字符索引来绘制一个字母或图标。

以下是将文本绘制到ImageSource的代码

private static ImageSource CreateGlyph(string text, 
        FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, 
        FontStretch fontStretch, Brush foreBrush)
{
    if (fontFamily != null && !String.IsNullOrEmpty(text))
    {
        Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
        GlyphTypeface glyphTypeface;
        if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                throw new InvalidOperationException("No glyphtypeface found");

        ushort[] glyphIndexes = new ushort[text.Length];
        double[] advanceWidths = new double[text.Length];
        for (int n = 0; n < text.Length; n++)
        {
            ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];
            glyphIndexes[n] = glyphIndex;
            double width = glyphTypeface.AdvanceWidths[glyphIndex] * 1.0;
            advanceWidths[n] = width;
        }

        GlyphRun gr = new GlyphRun(glyphTypeface, 0, false, 1.0, glyphIndexes,
                                    new Point(0, 0), advanceWidths, 
                                    null, null, null, null, null, null);
        GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing(foreBrush, gr);
        return new DrawingImage(glyphRunDrawing);

    }
    return null;
}

限制

所有属性(TextFontFamilyBrush)都是不可绑定的(因为MarkupExtension不是DependencyObject)。

大小不是直接管理的,因为glyph被渲染以在容器对象中拉伸。

您必须将类放在单独的程序集中(如WpfTool),才能使其在设计模式下工作(这是Visual Studio的一个已知错误)。

历史

  • 2013年8月:第一个版本
© . All rights reserved.