如何在Silverlight中了解本地字体名称

8
在Silverlight 4中,我需要知道我机器上的所有字体名称。 使用...
 var typefaces = System.Windows.Media.Fonts.SystemTypefaces;

        foreach (System.Windows.Media.Typeface face in typefaces)
        {

            System.Windows.Media.GlyphTypeface a;
            face.TryGetGlyphTypeface(out a);
            FontSource fs = new FontSource(a);

           var b = a.FontFileName;

我只能获取字体文件名,但实际上我们需要字体名称才能显示它....

如何获取这样的信息?

谢谢大家!

3个回答

4

为Silverlight生成查找表:

WPF具备此功能,但Silverlight没有。

如果您在调试器中查看System.Windows.Media.Typeface对象,则字体除了2个版本号和FontUri(即文件名)外不包含任何内容。

您可以通过在WPF下运行代码来提取所有文件名和匹配字体名称来生成查找字典,但您需要在安装了要覆盖的每种字体的计算机上执行此操作。

以下WPF代码提取了这样一个表格(此表格包含所有语言的字体名称,因此您可能需要添加过滤器,例如“en-us”):

    foreach (var font in System.Windows.Media.Fonts.SystemTypefaces)
    {
        System.Windows.Media.GlyphTypeface glyphTypeface;
        font.TryGetGlyphTypeface(out glyphTypeface);
        var dictionary = font.FaceNames;
        foreach (var language in dictionary.Keys)
        {
            Debug.WriteLine(string.Format("\"{0}\", \"{1}\", \"{2}\"", glyphTypeface.FontUri.Segments[glyphTypeface.FontUri.Segments.Count()-1], language, dictionary[language]));
        }
    }

以下是部分输出结果,可以轻松地格式化为表格或在 Silverlight 中加载为字典:
"ARIAL.TTF", "ca-es", "Normal"
"ARIAL.TTF", "cs-cz", "obyčejné"
"ARIAL.TTF", "da-dk", "normal"
"ARIAL.TTF", "de-de", "Standard"
"ARIAL.TTF", "el-gr", "Κανονικά"
"ARIAL.TTF", "en-us", "Regular"
"ARIAL.TTF", "es-es", "Normal"
"ARIAL.TTF", "es-mx", "Normal"
"ARIAL.TTF", "eu-es", "Arrunta"
"ARIAL.TTF", "fi-fi", "Normaali"
"ARIAL.TTF", "fr-ca", "Normal"
"ARIAL.TTF", "fr-fr", "Normal"
"ARIAL.TTF", "hu-hu", "Normál"
"ARIAL.TTF", "it-it", "Normale"
"ARIAL.TTF", "nb-no", "Normal"
"ARIAL.TTF", "nl-nl", "Standaard"
"ARIAL.TTF", "pl-pl", "Normalny"
"ARIAL.TTF", "pt-br", "Normal"
"ARIAL.TTF", "pt-pt", "Normal"
"ARIAL.TTF", "ru-ru", "Обычный"
"ARIAL.TTF", "sk-sk", "Normálne"
"ARIAL.TTF", "sl-si", "Navadno"
"ARIAL.TTF", "sv-se", "Normal"
"ARIAL.TTF", "tr-tr", "Normal"
"ARIAL.TTF", "vi-vn", "thường"
"ARIALN.TTF", "en-us", "Narrow"
"ARIALI.TTF", "ca-es", "Cursiva"
"ARIALI.TTF", "cs-cz", "kurzíva"
"ARIALI.TTF", "da-dk", "kursiv"
"ARIALI.TTF", "de-de", "Kursiv"
"ARIALI.TTF", "el-gr", "Πλάγια"
"ARIALI.TTF", "en-us", "Italic"
"ARIALI.TTF", "es-es", "Cursiva"
"ARIALI.TTF", "es-mx", "Cursiva"
"ARIALI.TTF", "eu-es", "Etzana"
"ARIALI.TTF", "fi-fi", "Kursivoitu"
"ARIALI.TTF", "fr-ca", "Italique"
"ARIALI.TTF", "fr-fr", "Italique"
"ARIALI.TTF", "hu-hu", "Dőlt"
"ARIALI.TTF", "it-it", "Corsivo"
"ARIALI.TTF", "nb-no", "Kursiv"
"ARIALI.TTF", "nl-nl", "Cursief"
"ARIALI.TTF", "pl-pl", "Kursywa"
"ARIALI.TTF", "pt-br", "Itálico"
"ARIALI.TTF", "pt-pt", "Itálico"
"ARIALI.TTF", "ru-ru", "Курсив"
"ARIALI.TTF", "sk-sk", "Kurzíva"
"ARIALI.TTF", "sl-si", "Poševno"
"ARIALI.TTF", "sv-se", "Kursiv"
"ARIALI.TTF", "tr-tr", "İtalik"
"ARIALI.TTF", "vi-vn", "nghiêng"
"ARIALNI.TTF", "en-us", "Narrow"
"ARIALBD.TTF", "ca-es", "Negreta"
"ARIALBD.TTF", "cs-cz", "tučné"
"ARIALBD.TTF", "da-dk", "fed"
"ARIALBD.TTF", "de-de", "Fett"
"ARIALBD.TTF", "el-gr", "Έντονα"
"ARIALBD.TTF", "en-us", "Bold"
"ARIALBD.TTF", "es-es", "Negrita"
"ARIALBD.TTF", "es-mx", "Negrita"
"ARIALBD.TTF", "eu-es", "Lodia"
"ARIALBD.TTF", "fi-fi", "Lihavoitu"

0
我也尝试过使用System.Windows.Media.Fonts.SystemTypefaces,但正如您所提到的那样,它只会给出字体文件名。在网上大量阅读和研究后,我决定使用P/Invoke来解决这个问题。如果您有选择以我所拥有的升级信任的OOB(离线浏览器)方式运行您的应用程序,则以下P/Invoke解决方案将非常有效。感谢www.pinvoke.net提供的所有方法/结构定义。
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Security;
namespace Utils
{
  [SecurityCritical]
  public class FontsCollection
  {

    #region Types
    delegate int EnumFontDelegate(IntPtr lpelfe, IntPtr lpntme, EnumFontsType FontType, int lParam);
    enum EnumFontsType
    {
      DEVICE_FONTTYPE = 0x0000,
      RASTER_FONTTYPE = 0x0001,
      TRUETYPE_FONTTYPE = 0x0004
    };

    #region LOGFONT definition
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class LOGFONT
    {
      public int lfHeight;
      public int lfWidth;
      public int lfEscapement;
      public int lfOrientation;
      public FontWeight lfWeight;
      [MarshalAs(UnmanagedType.U1)]
      public bool lfItalic;
      [MarshalAs(UnmanagedType.U1)]
      public bool lfUnderline;
      [MarshalAs(UnmanagedType.U1)]
      public bool lfStrikeOut;
      public FontCharSet lfCharSet;
      public FontPrecision lfOutPrecision;
      public FontClipPrecision lfClipPrecision;
      public FontQuality lfQuality;
      public FontPitchAndFamily lfPitchAndFamily;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
      public string lfFaceName;
    }

    public enum FontWeight : int
    {
      FW_DONTCARE = 0,
      FW_THIN = 100,
      FW_EXTRALIGHT = 200,
      FW_LIGHT = 300,
      FW_NORMAL = 400,
      FW_MEDIUM = 500,
      FW_SEMIBOLD = 600,
      FW_BOLD = 700,
      FW_EXTRABOLD = 800,
      FW_HEAVY = 900,
    }

    public enum FontCharSet : byte
    {
      ANSI_CHARSET = 0,
      DEFAULT_CHARSET = 1,
      SYMBOL_CHARSET = 2,
      SHIFTJIS_CHARSET = 128,
      HANGEUL_CHARSET = 129,
      HANGUL_CHARSET = 129,
      GB2312_CHARSET = 134,
      CHINESEBIG5_CHARSET = 136,
      OEM_CHARSET = 255,
      JOHAB_CHARSET = 130,
      HEBREW_CHARSET = 177,
      ARABIC_CHARSET = 178,
      GREEK_CHARSET = 161,
      TURKISH_CHARSET = 162,
      VIETNAMESE_CHARSET = 163,
      THAI_CHARSET = 222,
      EASTEUROPE_CHARSET = 238,
      RUSSIAN_CHARSET = 204,
      MAC_CHARSET = 77,
      BALTIC_CHARSET = 186,
    }

    public enum FontPrecision : byte
    {
      OUT_DEFAULT_PRECIS = 0,
      OUT_STRING_PRECIS = 1,
      OUT_CHARACTER_PRECIS = 2,
      OUT_STROKE_PRECIS = 3,
      OUT_TT_PRECIS = 4,
      OUT_DEVICE_PRECIS = 5,
      OUT_RASTER_PRECIS = 6,
      OUT_TT_ONLY_PRECIS = 7,
      OUT_OUTLINE_PRECIS = 8,
      OUT_SCREEN_OUTLINE_PRECIS = 9,
      OUT_PS_ONLY_PRECIS = 10,
    }

    public enum FontClipPrecision : byte
    {
      CLIP_DEFAULT_PRECIS = 0,
      CLIP_CHARACTER_PRECIS = 1,
      CLIP_STROKE_PRECIS = 2,
      CLIP_MASK = 0xf,
      CLIP_LH_ANGLES = (1 << 4),
      CLIP_TT_ALWAYS = (2 << 4),
      CLIP_DFA_DISABLE = (4 << 4),
      CLIP_EMBEDDED = (8 << 4),
    }

    public enum FontQuality : byte
    {
      DEFAULT_QUALITY = 0,
      DRAFT_QUALITY = 1,
      PROOF_QUALITY = 2,
      NONANTIALIASED_QUALITY = 3,
      ANTIALIASED_QUALITY = 4,
      CLEARTYPE_QUALITY = 5,
      CLEARTYPE_NATURAL_QUALITY = 6,
    }

    [Flags]
    public enum FontPitchAndFamily : byte
    {
      DEFAULT_PITCH = 0,
      FIXED_PITCH = 1,
      VARIABLE_PITCH = 2,
      FF_DONTCARE = (0 << 4),
      FF_ROMAN = (1 << 4),
      FF_SWISS = (2 << 4),
      FF_MODERN = (3 << 4),
      FF_SCRIPT = (4 << 4),
      FF_DECORATIVE = (5 << 4),
    }
    #endregion

    #endregion

    #region Fields
    private IList<string> _fontNames;
    private IntPtr _fpEnumProc;
    private EnumFontDelegate _enumFontDelegate;
    private static FontsCollection _default;
    #endregion

    #region External APIs
    [DllImport("gdi32.dll")]
    private static extern int EnumFontFamilies(IntPtr hdc, string fontFamily, IntPtr lpEnumFontFamExProc, IntPtr lParam);

    [DllImport("user32.dll")]
    private static extern IntPtr GetDesktopWindow();

    [DllImport("user32.dll")]
    private static extern IntPtr GetDC(IntPtr hwnd);

    [DllImport("user32.dll")]
    private static extern IntPtr ReleaseDC(IntPtr hdc); 
    #endregion

    #region Properties
    public IEnumerable<string> InstalledFontNames
    {
      get
      {
        if (null == _fontNames)
        {
          BuildFontList();
        }
        return _fontNames.AsEnumerable();
      }
    }
    public static FontsCollection Default
    {
      get
      {
        return _default ?? (_default = new FontsCollection());
      }
    }
    #endregion

    #region Win32 callback
    [System.Runtime.InteropServices.AllowReversePInvokeCalls]
    private int EnumFontFamiliesExProc(IntPtr lpelfe, IntPtr lpntme, EnumFontsType FontType, int lParam)
    {
      LOGFONT logFont = new LOGFONT();
      Marshal.PtrToStructure(lpelfe, logFont);

      //we dont like duplicate names
      if (!_fontNames.Contains(logFont.lfFaceName, StringComparer.OrdinalIgnoreCase))
      {
        _fontNames.Add(logFont.lfFaceName);
      }
      // Non-zero return continues enumerating
      return 1;
    }

    #endregion

    #region Methods
        private void BuildFontList()
    {
      // Need an HDC to pass to EnumFontFamilies
      IntPtr hwnd = GetDesktopWindow();
      IntPtr hdc = GetDC(hwnd);
      try
      {
        LOGFONT logFont = new LOGFONT();

        _enumFontDelegate = new EnumFontDelegate(EnumFontFamiliesExProc);
        _fpEnumProc = Marshal.GetFunctionPointerForDelegate(_enumFontDelegate);
        _fontNames = new List<String>();
        EnumFontFamilies(hdc, null, _fpEnumProc, IntPtr.Zero);
        _fontNames = _fontNames.OrderBy(font => font).ToList();
      }
      finally
      {
        if (hdc != IntPtr.Zero)
        {
          ReleaseDC(hdc);
        }
      }
    }

      #endregion  
  }
}

使用这个类非常简单。下面是一个示例XAML标记

<UserControl x:Class="SLTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">

    <Grid x:Name="LayoutRoot" Background="White">
        <ComboBox ItemsSource="{Binding InstalledFontNames}" Height="50"/>
    </Grid>
</UserControl>

在 XAML 页面的代码后台中添加以下内容。
public partial class MainPage : UserControl
{
    public MainPage()
    {
      InitializeComponent();
      DataContext = Utils.FontsCollection.Default;
    }
}

0

查看这个答案。

最终我在服务器上使用了Fonts.SystemFontFamilies(在PresentationCore dll中),通过服务调用将结果(从Source属性)发送到Silverlight应用程序。虽然不完美,但这是我能找到的最好的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接