在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,但实际上我们需要字体名来显示它....
如何获得此类信息?
谢谢大家!
答案 0 :(得分:4)
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"
答案 1 :(得分:0)
我最终在SERVER上使用Fonts.SystemFontFamilies
(在PresentationCore dll中),通过服务调用将结果(来自Source
属性)发送到Silverlight应用程序。不完美,但我能找到最好的。
答案 2 :(得分:0)
我也尝试使用System.Windows.Media.Fonts.SystemTypefaces
,但正如您所提到的,它只提供了字体文件名。在网上做了大量的阅读和研究后,我决定使用P / Invoke来解决这个问题。如果你可以像我一样选择将你的应用程序作为OOB(Out of Browser)运行,那么下面的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;
}
}