IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Windows 10 UWP开发:获取系统字体及字符

    汪宇杰发表于 2016-02-03 01:59:12
    love 0

    以前WPF里有个{x:Static Fonts.SystemFontFamilies}可以很方便的绑定系统字体列表,结果UWP里被微软撸掉了,Stupid!

    这两天写了个UWP版的字符映射表APP,正好要用到字体功能,于是研究了一下。

    在UWP里获取系统字体必须得用DirectX渲染,没错,就是做游戏用的那个DX。

    从NuGet引这3个包:

    "SharpDX": "3.0.1",
    "SharpDX.Direct2D1": "3.0.1",
    "SharpDX.DXGI": "3.0.1"

    然后写个InstalledFont类:

    这个类的代码是我改进过的,SharpDX官方的代码是会爆的,在一些中文系统的计算机上会产生错误的index,然后爆一个HResult什么的看也看不懂但是觉得很牛逼然而还是没有什么卵用的错。

    其中,Name是字体名称,FamilyIndex是字体在它所属Family中的序号,Index是字体在系统所有字体列表中的序号。

    GetFonts()方法就能返回所有的系统字体。

    public class InstalledFont
    {
        public string Name { get; set; }
    
        public int FamilyIndex { get; set; }
    
        public int Index { get; set; }
    
        public static List<InstalledFont> GetFonts()
        {
            var fontList = new List<InstalledFont>();
    
            var factory = new Factory();
            var fontCollection = factory.GetSystemFontCollection(false);
            var familyCount = fontCollection.FontFamilyCount;
    
            for (int i = 0; i < familyCount; i++)
            {
                var fontFamily = fontCollection.GetFontFamily(i);
                var familyNames = fontFamily.FamilyNames;
                int index;
    
                if (!familyNames.FindLocaleName(CultureInfo.CurrentCulture.Name, out index))
                {
                    if (!familyNames.FindLocaleName("en-us", out index))
                    {
                        index = 0;
                    }
                }
    
                string name = familyNames.GetString(index);
                fontList.Add(new InstalledFont()
                {
                    Name = name,
                    FamilyIndex = i,
                    Index = index
                });
            }
    
            return fontList;
        }
    
        public List<Character> GetCharacters()
        {
            var factory = new Factory();
            var fontCollection = factory.GetSystemFontCollection(false);
            var fontFamily = fontCollection.GetFontFamily(FamilyIndex);
    
            var font = fontFamily.GetFont(Index);
    
            var characters = new List<Character>();
            var count = 65535;
            for (var i = 0; i < count; i++)
            {
                if (font.HasCharacter(i))
                {
                    characters.Add(new Character()
                    {
                        Char = char.ConvertFromUtf32(i),
                        UnicodeIndex = i
                    });
                }
            }
    
            return characters;
        }
    }
    

    里面的Character类型代表一个字符。

    public class Character
    {
        public string Char { get; set; }
    
        public int UnicodeIndex { get; set; }
    }
    

    前台绑定(非MVVM的写法,当然你也可以自行用MVVM装逼)

    var fontList = InstalledFont.GetFonts();
    CmbFontFamily.ItemsSource = fontList;
    
    <ComboBox Grid.Row="0" x:Name="CmbFontFamily" x:Uid="CmbFontFamily" Width="300" SelectionChanged="CmbFontFamily_OnSelectionChanged" SelectedValuePath="Name">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
    </ComboBox>

    如果要显示Unicode编码,就用Character里的那个UnicodeIndex。在WIN32的字符映射表里显示的是看上去很牛逼的U+EXXXX这样的,我们也可以装一下逼。

    C#里面int转16进制的string只要ToString("X")就好了,然后再ToUpper()全部大写,把逼装完:

    TxtUnicode.Text = "U+" + ch.UnicodeIndex.ToString("x").ToUpper();


沪ICP备19023445号-2号
友情链接