03、矢量图形查询工具(Symbol Unicode)_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 03、矢量图形查询工具(Symbol Unicode)

03、矢量图形查询工具(Symbol Unicode)

 2015/4/20 10:32:11  段博琼  程序员俱乐部  我要评论(0)
  • 摘要:目前的软件开发中,很多地方都使用到了矢量图标,在Metroapp的开发中,可以使用Windows系统图标(02、Universalapp中按钮图标使用),包括SegoeUISymbol、SegoeMDL2Assets(Windows10新添加)、SegoeUIEmoji等。不过在开发中,遇到了一个问题,就是系统自带的“字符映射表”中很多图标太小了,又不能调整大小,不方便浏览,于是自己动手写了一个矢量图形的Unicode查询工具(使用WPF写的)
  • 标签:工具

  

   目前的软件开发中,很多地方都使用到了矢量图标,在 Metro app 的开发中,可以使用 Windows

系统图标(02、Universal app 中按钮图标使用 ),包括 Segoe UI Symbol、Segoe MDL2 Assets(Windows10 新添加)、

Segoe UI Emoji 等。

  不过在开发中,遇到了一个问题,就是系统自带的 “字符映射表” 中很多图标太小了,又不能调整大小

,不方便浏览,于是自己动手写了一个矢量图形的 Unicode 查询工具(使用 WPF 写的),涉及到了 Unicode

转码的一些技术。

 

系统自带的 “字符映射表” :

 

1、"矢量图形查询工具" 运行效果:

  1)主窗口:

 

  2) 可以同时打开 Segoe UI Emoji  窗口:

 

Segoe UI Symbol 窗口:

 

Segoe MDL2 Assets 窗口:

 

 

2、不同编码,占用的字节关系:

  1)ASCII码:一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。

   UTF-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。

   Unicode编码:一个英文等于两个字节,一个中文(含繁体)等于两个字节。

     符号:英文标点占一个字节,中文标点占两个字节。举例:英文句号“.”占1个字节的大小,中文句号“。”占2个字节的大小。

 

  2)示例:在代码和 xml 中表示 unicode:

 <Label Content="示例:" Grid.Row="5"/>
 <StackPanel Orientation="Horizontal" Grid.Row="5" Grid.Column="1">
     <!--将字符的 Unicode 的写在 xml 文件中时,需要使用转码格式-->
     <TextBlock FontFamily="Segoe UI Symbol" Text="&#xE189;"/>
     
     <!--在 C# 页面中,用代码赋值-->
     <TextBlock FontFamily="Segoe UI Symbol" x:Name="txtSample" Margin="30,0,0,0"/>
 </StackPanel>

 

   在 C# 代码中(与 C++ 表示方式相同),unicode 书写的格式为以 '\u' 开头(注意 u 为小写),后面是大于4位的 十六进制数,格式需要正确:

 txtSample.Text = "\uE189";

 

   显示效果:

 

 

   如果格式不对,不会通过编译:

 

 

 3、遍历当前 Windows系统上安装的所有字体:

  1)首页 MainWindow.xaml 中的代码:

    <Label Content="所有字体:" Grid.Row="1"/>
    <ComboBox x:Name="fullFamily" Grid.Row="1" Grid.Column="1">
        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel/>
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}"  Margin="30,5,0,0" Background="Transparent"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

    <Label Content="打开查询窗口:" Grid.Row="3"/>
    <ListBox x:Name="listBox" Grid.Row="3" Grid.Column="1">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" Margin="30,5,0,0" Background="Transparent"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

 

   2)C# 页面代码:

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    FontFamilyMapCollection ffCollection;

    // 遍历当前系统上的所有字体。参考 MSDN// https://msdn.microsoft.com/zh-cn/library/system.windows.media.fontfamily.aspx
    foreach (FontFamily fontFamily in Fonts.SystemFontFamilies)
    {
// 这里把 “图标字体”显示到 ListBox 中,“所有字体” 显示到 ComboBox 中
if (fontFamily.Source == "Segoe UI Symbol" || fontFamily.Source == "Segoe MDL2 Assets" || fontFamily.Source == "Segoe UI Emoji") { ffCollection = fontFamily.FamilyMaps; listBox.Items.Add(fontFamily.Source); } fullFamily.Items.Add(fontFamily.Source); } } // 选中相应 “图标字体” 后,跳转到 “查看窗口” private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { string fontName = (sender as TextBlock).Text; SymbolWindow sw = new SymbolWindow(); // 使用静态属性,作为参数传递 SymbolWindow.CurrentFontFamily = new FontFamily(fontName); // 选中的字体 sw.Show(); }

 

 4、浏览窗口:

  1)SymbolWindow.xaml 文件 ,窗口的 x:Name 设置为 myWindow

<ListView x:Name="listBox" ItemTemplate="{StaticResource template}">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <!--Items 面板的宽度与窗口宽度绑定,根据窗口改变排列。防止显示为单行-->
            <WrapPanel Orientation="Horizontal" Width="{Binding ActualWidth,ElementName=myWindow}"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

 

   2)在  this.Loaded 事件中,调用 FontItem.EnumeratorFontFamily(CurrentFontFamily) 静态方法,把相关字体中

    包含的所有 Unicode 编码转换为相应的 字符:

 /// <summary>
 /// 作为从 MainWindow.xaml 传递来的参数
 /// </summary>
 public static FontFamily CurrentFontFamily;

 private void Segoe_UI_Symbol_Loaded(object sender, RoutedEventArgs e)
 {
     // FontFamily ff = new FontFamily("Segoe MDL2 Assets");

     if (CurrentFontFamily != null)
     {
         this.FontFamily = CurrentFontFamily;

         this.Title = " 当前字体 : " + CurrentFontFamily.Source;

         listBox.ItemsSource = FontItem.EnumeratorFontFamily(CurrentFontFamily);
     }
 }

 

 

 5、FontItem 类定义,用来显示绑定和 Unicode 的转码:

  1)把十六进制 unicode 转换为 byte 数组,再调用 Encoding.Unicode.GetChars(array); 方法,转换为

相应字符:

 // Unicode 转换为 “符号” 字符表示
 // 例如,0xE189 转换为 byte[]{ 137, 225 }
 byte[] bytes = new byte[]
  {
    (byte) Key,
    (byte) (Key >> 8)
  };
 
 string Character = ByteToString(bytes);

 

 //二进制数转换成字符
 public static string ByteToString(byte[] array)
 {
     var enc = Encoding.Unicode;
     var chars = enc.GetChars(array);
     return new string(chars);
 }

   

   FontItem.cs 文件 全部代码:

class="code_img_closed" src="/Upload/Images/2015042010/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('1cdd706a-96b4-4485-93d1-82776d969791',event)" src="/Upload/Images/2015042010/2B1B950FA3DF188F.gif" alt="" />
  class FontItem
    {
        public string key { set; get; }
        public string value { get; set; }

        public string font { set; get; }
        
        public static List<FontItem> EnumeratorFontFamily(FontFamily family)
        {
            Dictionary<int, FontItem> fonts = new Dictionary<int, FontItem>();

            var typefaces = family.GetTypefaces();
            foreach (Typeface typeface in typefaces)
            {
                // 对应字体文件中包含的物理字体
                GlyphTypeface glyph;

                typeface.TryGetGlyphTypeface(out glyph);

                // 根据字体“CMAP”表的定义获取 Unicode 码位与标志符号索引之间的名义映射。 
                IDictionary<int, ushort> characterMap = glyph.CharacterToGlyphMap;


                foreach (KeyValuePair<int, ushort> kvp in characterMap)
                {
                    //  Console.WriteLine(String.Format("{0}:{1}", kvp.Key, kvp.Value));

                    int Key = kvp.Key; // 没有用到 kvp.Value

                    // 如果大于 0xffff(为空字符,显示为小方框),则跳出循环
                    if (Key > 0xffff) // 0 ~ 65535
                    {
                        break;
                    }
                    
                    // 方法 1: Unicode 转换为 “符号” 字符表示
                    // 例如,0xE189 转换为 byte[]{ 137, 225 }
                    byte[] bytes = new byte[]
                     {
                       (byte) Key,
                       (byte) (Key >> 8)
                     };
                    
                    string Character = ByteToString(bytes);

                    // 方法 2:Unicode 转换为 “符号” 字符
                    //       可以用来转换 Key= 65535 以下的 Unicode,如果大于 65535,则会抛出:
                    //       “ System.OverflowException:值对于字符太大或太小” 的异常
                    // char c = Convert.ToChar(Key);
                    // string Character = c.ToString();

                    // 过滤掉空字符
                    if (!string.IsNullOrEmpty(Character) &&
                        !string.IsNullOrWhiteSpace(Character) &&
                        !fonts.Keys.Contains(Key)// 去掉重复的
                       )
                    {

                        fonts.Add(Key, new FontItem { key = Key.ToString("X4"), font = Character });
                    }
                }
            }

            return fonts.Values.ToList();
        }
        

        // 把二进制数转换成字符
        public static string ByteToString(byte[] array)
        {
            var enc = Encoding.Unicode;
            var chars = enc.GetChars(array);
            return new string(chars);
        }
    }
View Code

 

 

工具直接下载 (基于 .net framework 4.5)

源代码下载

 

 

 

参考及相关阅读:

How to: Enumerate Installed Fonts

字体文件中包含的字符判断

百度百科:Unicode

发表评论
用户名: 匿名