Click here to Skip to main content
Click here to Skip to main content

Character Map in WPF

, 3 Jun 2012
Rate this:
Please Sign up or sign in to vote.
Character Map is a free utility found in Windows Machines. It is similar to the "Insert Symbol" tool in few MS Office applications. This article explains how to implement this tool using WPF.

Introduction   

The Character Map utility is free on all Windows machines and can be used to copy and paste accented letters and other foreign language characters into any Windows application. The Character Map is similar to the Insert Symbol tool found in some Windows applications such as Microsoft Word.

This article explains how to implement this tool using WPF with great performance. This tool can be easily integrated into any of your WPF applications easily.  

Using the code 

When I was start thinking about implementing this in WPF, I realized the main challenge would be the performance. But the native character map in Windows is really faster and will give a nice user experience. So I am sure this article will be valid only if this tool would also give the same experience. 

Getting the symbols  

Let me first start with getting the symbols from Font files. Populating a ComboBox with installed Font families is not a big deal in WPF. The article explains how to do that. Also the code is so simple.

<ComboBox ItemsSource="{x:Static Fonts.SystemFontFamilies}" />

To get the available symbols from a Typeface, first iterate through the typefaces in a Font family and choose the appropriate one. Once you got the Typeface, get the glyph which gives you the character map dictionary. 

IDictionary<int, ushort> characterMap;
foreach (Typeface typeface in font.GetTypefaces())
{
   typeface.TryGetGlyphTypeface(out glyph);
   if (glyph != null)
   {
     characterMap = glyph.CharacterToGlyphMap;
   }
}

The variable characterMap is a dictionary, which stores the unicode values for our symbols. So now we can go ahead and display the symbols in UI.

Symbols UI  

As I previously stated, the performance will be a major bottle neck in WPF. Since some font families may have more than 20,000 symbols. In case if you like to show them in a traditional ListBox with a wrap panel you would lose the user experience which Windows default character map has. I am sure there is a Virtualization Wrap Panel for WPF posted in this code project article. But I am going to use something better in which we don't need to care about the containers generation and disposing them.

I am going to use a Canvas and I decided my viewport size would be 345 X 250 and not more than that. Based on this I have placed 150 SymbolView (view that holds the symbol) objects into the canvas in horizontal wrap manner. Each view will have a textbox displaying the corresponding text of the symbol unicode.

<Border x:Class="CharacterMap.SymbolView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         RenderTransformOrigin="0.5, 0.5"
         mc:Ignorable="d" Width="23" 
         Height="25" Background="White"
         d:DesignHeight="300" d:DesignWidth="300" 
         BorderBrush="Black" BorderThickness="0 0 1 1">
    <TextBlock Text="" x:Name="charcter" FontSize="17" 
      VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>

So now, everytime the user choose the Font family in the Combo Box, I will update the 150 tiles with corresponding symbols. I am using a Dispatcher timer to ensure the things will not kill the UI thread. 

private void Repaint(double value)
{
    i = Convert.ToInt32((value / 0.1) * 15);
    item_index = 0;
    timer.Start();
} 

In the tick event of the timer, I am updating the tiles,

void timer_Tick(object sender, EventArgs e)
{
     try
     {
         SymbolView view = canvas.Children[item_index] as SymbolView;
         int index = characterMap.Keys.ElementAt(i);
         char c = Convert.ToChar(index);
         view.charcter.Text = c.ToString();
         item_index++;
         i++;
     }
     catch (Exception)
     {
         SymbolView view = canvas.Children[item_index] as SymbolView;
         view.charcter.Text = "";
         item_index++;
         i++;
     }
     if (item_index >= 150)
     {
         timer.Stop();
         item_index = 0;
     }
}

Scrolling  

Now its time to handle the Scroll bar. Since I am not using the WPF Items Control, the scrollbars will not work for my case. And it is clear that we will be having only 150 tiles in the UI. So the idea is, we have a ScrollBar near to the canvas showing symbols. Based on the scroll offset, the entire tiles are repainted with updated symbols. The work, is we should match the scrollbar offset to the current symbols in the view.  

The base idea is, even though we got 20,000 symbols for a Font Family, we are showing only 150 symbols. On scrolling we will update the symbols based on the offset.   

private void OnScroll(object sender, ScrollEventArgs e)
{
   Repaint(e.NewValue);
}

private void Repaint(double value)
{
    i = Convert.ToInt32((value / 0.1) * 15);
    item_index = 0;
    timer.Start();
}  

So now we got a nice scrolling effect even though we have huge number of symbols. Also I have added the Key Down behavior. You could also navigate through the symbols using the Keyboard. A textbox is also there to select and copy the symbols. 

History 

1. Enable Live updates to scrolling.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jawahar Suresh Babu
Software Developer (Senior)
India India
Jawahar working as a Senior Development Engineer in Aditi Technologies,Bangalore, India. Specialist in all XAML frameworks. Very passionate on UX Design and Development. Skilled in Expression Blend, Design, WPF, Silverlight, Windows Phone 7/8, Windows 8. Good knowledge in Entity Framework, SQLite and SQL Server also. Also had good experience with PRISM, MVVM, Caliiburn Micro and other design patterns.
 
He developed few products for Syncfusion Inc. Also working on some freelancing projects. Worked as a lead developer of Metro Studio from Syncfusion Inc.
 
An active freelancer. http://xamlfactory.elance.com
 
http://about.me/jawahars
 
http://wpfplayground.com/
Follow on   Twitter   LinkedIn

Comments and Discussions

 
Questionvery Helpfull Pinmemberamigoface15-May-14 6:10 
Questionimplement the same function in winform Pinmembergiske zhang27-Aug-13 0:17 
NewsGood job! PinmemberMember 1023144625-Aug-13 17:22 
QuestionHow to get the unicode of each character in the font? PinmemberHamdy Ahmed21-Mar-13 12:11 
GeneralMy vote of 4 PinmemberRavi Lodhiya4-Jun-12 11:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 3 Jun 2012
Article Copyright 2012 by Jawahar Suresh Babu
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid