【问题标题】:how to know local font names in silverlight如何知道silverlight中的本地字体名称
【发布时间】:2010-04-24 18:02:45
【问题描述】:

在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;

...

我只能得到 FontFileName 但实际上我们需要字体名来显示它....

如何获得这些信息?

谢谢大家!

【问题讨论】:

    标签: silverlight fonts silverlight-4.0


    【解决方案1】:

    为 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"
    

    【讨论】:

      【解决方案2】:

      See this answer.

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

      【讨论】:

        【解决方案3】:

        我也尝试使用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;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2014-06-09
          • 2019-09-13
          • 2022-08-24
          • 1970-01-01
          • 2016-01-01
          • 2011-09-06
          • 1970-01-01
          • 2016-02-18
          • 2011-03-08
          相关资源
          最近更新 更多