Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / XAML

Character Map in WPF

Rate me:
Please Sign up or sign in to vote.
4.73/5 (8 votes)
3 Jun 2012CPOL3 min read 48.5K   2.3K   15   6
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.  

Image 1

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.

XML
<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. 

C#
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.

XML
<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. 

C#
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,

C#
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.   

C#
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)


Written By
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/

Comments and Discussions

 
Questionhelp about character map Pin
Member 1283175421-Sep-17 22:42
Member 1283175421-Sep-17 22:42 
Questionvery Helpfull Pin
amigoface15-May-14 6:10
amigoface15-May-14 6:10 
Questionimplement the same function in winform Pin
giske zhang27-Aug-13 0:17
giske zhang27-Aug-13 0:17 
NewsGood job! Pin
giske zhang25-Aug-13 17:22
giske zhang25-Aug-13 17:22 
QuestionHow to get the unicode of each character in the font? Pin
Hamdy Ahmed21-Mar-13 12:11
Hamdy Ahmed21-Mar-13 12:11 
GeneralMy vote of 4 Pin
Ravi Lodhiya4-Jun-12 11:53
professionalRavi Lodhiya4-Jun-12 11:53 
Nice Article. Keep it Up!

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

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