(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Phone 7–Creating Custom Keyboard

(9 votes)
Pencho Popadiyn
>
Pencho Popadiyn
Joined Apr 30, 2008
Articles:   22
Comments:   97
More Articles
20 comments   /   posted on Feb 24, 2011
Categories:   Windows Phone

This article is compatible with the latest version of Silverlight for Windows Phone 7.

Last year, just for the Christmas holidays I bought my Windows Phone 7 device. I bought it for two reasons. First, it was Christmas and it was the perfect time to make a present for myself . Second, I wanted Windows Phone 7 because as a .NET developer having experience with Silverlight/WPF, I will be able to develop WP7 applications without spending any significant time for learning the WP7 programming model.

As an end user, I won’t comment the disadvantages of Windows Phone 7. It is normal, though we are talking for a system that is only few months old. However, as a developer I should “congratulate” Microsoft for their “great” politics. I am just wondering how is it possible to release the phone in around 30 countries, but at the same time their marketplace to be available in only 15 of them. I really cannot make it out. The fact that my Bulgarian credit card cannot get verified in the marketplace and I am not able to buy applications (some of the games are really awesome) is not such a pain. But the one thing I am really frustrated from is the fact that I am not allowed to create a developer account in the AppHub. Why? For the same reason, I am from Bulgaria, and the marketplace (AppHub) is not officially available here, and no one knows when it will be. As a result I am not able to even deploy my applications on the phone just for debugging.

Ok, enough lyrical digressions. Let’s get down to the brass tacks. My first task was to create some simple application in order to get a general idea about the development process. I had a few ideas in my mind. Initially, I was thinking of creating a simple game. However, a few friends of mine also bought WP7 devices. We had a discussion about the disadvantages of WP7. And they are really disappointed by the fact, that there isn’t a Bulgarian keyboard for WP7. That’s why I decided to try to create a custom Bulgarian keyboard for WP7. One last thing, I strongly recommend to take a look at the Andrea Boschin’s seriers. He discusses deeply the various aspects of the WP7 programming.

Soft Input Panel (SIP)

Let’s take a quick look at how the user enters information on a Windows Phone that is done via an on-screen keyboard, also known as a Soft Input Panel (SIP). Some devices offer a physical keyboard, too. For devices with a keyboard that slides away, the SIP will be displayed when the keyboard is closed. When the keyboard is opened, the SIP will be minimized.

Here is the moment to share a very interesting tip about the SIP and the Windows Phone emulator. Something I learnt a few days ago. I was wondering if it’s possible to use the keyboard on the host computer to enter text in the emulator, instead of the SIP. Well, it seems it is possible. To do that you have to press the Pause (Break) button. That will toggle between the keyboard on the host computer and the SIP.

There are some important issues you have to consider when working with the SIP. The first thing is that the SIP could not be overridden by both application developers and hardware manufacturers. On a WP7 the SIP experience will always be the same. The other thing is that you no longer get to control the display or hiding of the SIP. The SIP is automatically displayed or hidden when a control that requires text input receives or loses focus. As there are no events raised when the SIP is expanded or collapsed, you have to do some of this management yourself. The SIP is displayed when a TextBox gets focus and is hidden when the TextBox loses focus. Unfortunately, there is no way to know definitively if the SIP is visible as there is no explicit event or property indicating the state of the SIP. Although you could do your own tracking based on the TextBox focus, if the device has a physical keyboard, the SIP will not be displayed, making it impossible to know whether the SIP is being displayed. Also you should keep in mind that on devices that have a physical keyboard, the SIP will not be displayed when the keyboard is expanded. Or in other words it is currently impossible to modify the behavior of the SIP. The most commonly used text entry control is the TextBox (no surprise ). Although you cannot override the SIP, you can specify the InputScope of the TextBox. For more information, you could check out MSDN.

The requirements

Obviously, we don’t have any other options except to create an application that simulates the SIP. An application that simulates the SIP will be totally useless unless we add some additional tasks, such as sending email, writing messages, searching in Bing. Finally, our custom keyboard should look like the snapshot below:

Click to Enlarge

The sentence entered in the emulator, translated in English means “I want to eat. The keyboard should offer the standard Bulgarian 30 letters, system keys (Shift, Space, Enter, Backspace), additional widely used symbols (see the snapshot below), and various tasks (such as email task, search in Bing and send email).

Click to Enlarge

The email task

Let’s take a look at the different tasks that will be used in the application. Windows Phone 7 supports traditional email services such as POP3, IMAP, and SMTP, as well as synchronizing with Exchange Server. The e-mail tasks allow your application to compose emails and interact with users’ contacts to save and retrieve email addresses. For example, sending an email from your application is possible using the EmailComposeTask class. You can generate a pre-populated email by setting the To, Subject , and Body properties.

public static void SendEmail( string body )
{
    EmailComposeTask emailComposeTask = new EmailComposeTask
    {
        Body = body
    };
    emailComposeTask.Show();
}
 

Search in Bing task

The SearchTask class provides you with a way to invoke a Bing Web Search for a particular search string you supply through the SearchQuery property.

public static void BingSearch( string searchQuery )
{
    SearchTask searchTask = new SearchTask
    {
        SearchQuery = searchQuery
    };
    searchTask.Show();
}

Click to Enlarge

 

Phone and SMS tasks

Through the PhoneNumberChooserTask and SmsComposeTask classes you can request that the user selects phone numbers and send test messages. To allow user to select a phone number from the contact list on the phone, you just need to create a new instance of the PhoneNumberChooserTask class and invoke its Show method. Additionally you need to attach to the Completed event. Invoking the Show method will open the selector application.

Click to Enlarge

When a contact is selected, the selector application closes and the Completed event is raised. The selected phone number is wrapped in the PhoneNumber property of the passed event arguments.

public static void SendSms( string body )
{
    PhoneNumberChooserTask phoneChooseTask = new PhoneNumberChooserTask();
    EventHandler<PhoneNumberResult> temp = ( o, result ) =>
    {
        if ( result.TaskResult == TaskResult.Cancel )
        {
            return;
        }
 
        SmsComposeTask smsComposeTask = new SmsComposeTask
        {
            To = result.PhoneNumber,
            Body = body
        };
        smsComposeTask.Show();
    };
    phoneChooseTask.Completed -= temp;
    phoneChooseTask.Completed += temp;
    phoneChooseTask.Show();
}
 

Designing the keyboard

Let’s take a quick look at the structure of the application. Initially, I was planning to create the application as simple as possible. However, I later decided to put some efforts into the design. I wanted the created keyboard to be reusable, easily configurable and extensible. Well, you can’t achieve this without introducing several interfaces and abstract classes . The diagram below shows the heart of the application – the abstract Keyboard class. It exposes two protected abstract methods – GenerateContext and GenerateSecondaryContext.

Click to Enlarge

The idea here is that the keys you see (the Bulgarian letters) are not predefined. Instead, each concrete keyboard implementation provides its own keyboard context. Or in other words each derived type determines what will be shown on the screen. The only predefined keys are the system keys (space, backspace, enter). However, there are properties controlling their visibility, so you can hide them. Here is how the Bulgarian keyboard implementation looks like.

public class BulgarianKeyboard : Keyboard.Controls.Keyboard
{
    protected override KeyboardContext GenerateKeyboardContext()
    {
        KeyboardContext keyboardContext = new KeyboardContext();
        keyboardContext.Rows = 3;
 
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "я" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "в" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "е" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "р" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "т" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "ъ" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "у" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "и" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "о" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "п" ) );
 
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "а" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "с" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "д" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "ф" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "г" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "х" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "й" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "к" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "л" ) );
 
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "ч" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "з" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "ь" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "ц" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "ж" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "б" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "н" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "м" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "ш" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "щ" ) );
 
        return keyboardContext;
    }
 
    protected override KeyboardContext GenerateSecondaryKeyboardContext()
    {
        return new DefaultSecondaryKeyboardContext();
    }
}

The idea of the Expression class is to allow you to translate the letter or to allow you to modify what will be shown on the screen. For example, when you press the “Q” key, instead of showing “Q” on the screen you may want to show its ASCII code or something else. That is the target of the Expression class. As you may guess, the DefaultExpression class just returns the original symbol.

public sealed class DefaultExpression : Expression
{
    public override string Interpret( string symbol )
    {
        return symbol;
    }
}

The output screen control is also abstracted; it is not just a simple TextBlock.

 

We have the IOutputControl interface providing methods for modifying the displayed text. So if you like you can replace the default screen control with your own implementation. It is enough just to implement the IOutputControl interface. Finally, the last key member is the KeyboardScreenControl. This is the glue between the Keyboard and the IOutputControl.

So let’s put everything in practice.

<Grid x:Name="LayoutRoot">
    <Grid.Background>
        <ImageBrush ImageSource="/WP7.BulgarianKeyboard.Client;component/Background.jpg" />
    </Grid.Background>
 
    <keyboardControls:KeyboardScreenControl x:Name="Keyboard">
        <keyboardControls:KeyboardScreenControl.Keyboard>
            <bgKeyboard:BulgarianKeyboard />
        </keyboardControls:KeyboardScreenControl.Keyboard>
    </keyboardControls:KeyboardScreenControl>
 
</Grid>

And our custom keyboard application is ready.

Creating your own keyboard

You may note that there is a fourth button that I haven’t mentioned so far.

 

Here in Bulgaria we have the common practice to combine Bulgarian letters with English when writing emails, sms, forums etc. So I wanted to provide better experience to my compatriots. I wanted to create an EN keyboard as well, and give them the possibility to switch between the keyboard runtime. As I already mentioned it is enough to implement the abstract Keyboard class.

public class LatinKeyboard : Keyboard.Controls.Keyboard
{
    protected override KeyboardContext GenerateKeyboardContext()
    {
        KeyboardContext keyboardContext = new KeyboardContext();
        keyboardContext.Rows = 3;
 
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "q" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "w" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "e" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "r" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "t" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "y" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "u" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "i" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "o" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 0, "p" ) );
 
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "a" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "s" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "d" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "f" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "g" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "h" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "j" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "k" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 1, "l" ) );
 
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "z" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "x" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "c" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "v" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "b" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "n" ) );
        keyboardContext.KeyboardMapping.Add( new KeyMapping( 2, "m" ) );
 
        return keyboardContext;
    }
 
    protected override KeyboardContext GenerateSecondaryKeyboardContext()
    {
        return new DefaultSecondaryKeyboardContext();
    }
}

Then runtime, when the click event of the button is raised:

private void ChangeKeyboardButtonClick( object sender, EventArgs e )
{
    ApplicationBarIconButton changeKeyboardButton = sender as ApplicationBarIconButton;
    if(changeKeyboardButton == null)
    {
        return;
    }
 
    if ( ReferenceEquals( bgKeyboard, this.Keyboard.Keyboard ) )
    {
        this.Keyboard.Keyboard = this.latinKeyboard;
        changeKeyboardButton.Text = "bg";
    }
    else
    {
        this.Keyboard.Keyboard = this.bgKeyboard;
        changeKeyboardButton.Text = "en";
    }
}
 

What’s next

So that’s it. You could try to create your own keyboard. Or probably you may want to provide your own screen implementation. For me, the only option is to wait for Microsoft to expand their marketplace or maybe to find some workaround for creating an account in the AppHub. Meanwhile, I’ll continue to develop for WP7 in my free time. If you have any comments, feedback, suggestions or whatever it may be, do not hesitate to share with us.

Download Source Code

About the author

An MCPD and MCTS, Pencho Popadiyn is one of SilverlightShow team members with most Silverlight experience. He is actively involved in the development of complex modules for SilverlightShow, and a great deal of his experience is shared through SilverlightShow articles (check out Pencho's posts). He is also programming WP7 in his free time.

Pencho is a keen chess player, enjoys relaxation through jogging or nice music.


Subscribe

Comments

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by peSHIr on Feb 24, 2011 14:17

    I understand your frustration. It is already frustrating being in the Netherlands, but at least we don't have the problem of different characters and not being able to get a developer account.

    However, as soon as Bulgarian is supported, the problem you mention (switching between English and Bulgarian keyboard) is no problem, as WP7 supports selecting multiple keyboard layouts you normally switch between. This is just like doing so in Desktop Windows, and when you select more than one, the space bar on the SIP becomes smaller to show a language switch button, which also switches the keyboard layout. I know this works between EN/FR/DE which is already supported. There is no reason to suspect this won't work with Bulgarian and English as soon as WP7 supports Bulgaria.

    Of course, there is still no indication on when this will be. Good luck with that! :-/

  • ppopadiyn

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by ppopadiyn on Feb 27, 2011 21:21

    Hi IlEdVal,

    I could easily unlock my phone and deploy illegal applications (there are programs that allows me to download xap files from the marketplace), but that's not the point here.

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by RSK on Mar 20, 2011 05:59

    Hi

    Thanks a lot for sharing the code for writing custom keyboard. I am writing an app, in which I am planning to create a keyboard for my language. Is it okay if I use your WP7.Keyboard project in my app (with some modifications) ?

  • ppopadiyn

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by ppopadiyn on Mar 21, 2011 10:12

    Hi RSK,

    Thank you about your interest. Since I am providing the source code, feel free to use it and modify it as you want. Just when you are ready and upload it in the marketplace, let me see what is the end result :). If you have any further questions or remarks, let me know.

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by RSK on Mar 22, 2011 04:05

    Hi

    Thanks a lot :). By the way, only modification I am doing in the keyboard is the support for fonts. App I am writing needs to display keyboard in an Indian language. If I use unicode string mappings for indian language alphabets, they just show up as boxes in Windows Phone. Probably they don't have full support for Unicode characters yet. May be, you can have the in-built support for using Fonts in your base classes. That will be pretty useful for other people looking for same thing :).

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by maximv on Apr 04, 2011 00:15

    Hey,

    I think now you can create a developer account. Please visit www.yallaapps.com

    It is new service for countries that are not included into AppHub.

    let me know offline if you have any issues.

    I'll send you my email contact offline.

    good work.

    Maxim

     

     

  • ppopadiyn

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by ppopadiyn on Apr 04, 2011 11:26

    Hello maximv,

    I am familiar with the service that yallaapps provides. However as far as I know yallaapps is focused on countries from the Middle East and Africa. I think Bulgaria is not amongst the eligibible countries. Though thank you for the suggestion.

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by ruby on Apr 13, 2011 09:30
    that's really helpful. but wat to do if i want cursor position also 
  • ppopadiyn

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by ppopadiyn on Apr 15, 2011 09:06

    Hello ruby,

    If you want additional effects (as you said "cursor position") you have to exert additional efforts.

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by ruby on Apr 18, 2011 11:33
    actually i also made a custom keypad but i used textbox instead of textblock because i want some textbox features.The problem is on textbox focus. If i transfer the textbox focus to some other control then i will no get the cursor movement. i want cursor movement as well as my custom keypad should be on the top.
  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by Andrea Marras on 19:09

    Hi, does a homebrew app exist to change original keyboard into this one? 

    I am an italian user who wants to use a keyboard similar to the one you created (with latin letters), because your keyboard has the keys more distant then the wp7's original keys .. 

  • -_-

    RE: Windows Phone 7–Creating Custom Keyboard


    posted by metphone on May 21, 2011 12:28
    for Turkish keyboard you can use http://metphone.blogspot.com/
  • edwardlin

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by edwardlin on Jul 21, 2011 10:57

    Hi Pencho,

    I can't build your code with Windows Phone SDK 7.1 Beta 2. Error is "Xap packaging failed. Object reference not set to an instance of an object. WP7.BulgarianKeyboard.Client".

    Please help, thanks. 

     
  • ppopadiyn

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by ppopadiyn on Jul 26, 2011 07:45

    Hi edwardlin,

    This is very strange. I think you should not have any problems to compile the project for WP 7.1. In fact, I haven't installed the Mango tools on my PC yet. Did you try Clean Solution or Rebuild Solution? I really don't have any idea.

  • edwardlin

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by edwardlin on Jul 28, 2011 07:05

    Hi Pencho,

    Thanks for your reply. I rebuilded solution, but error is the same.

    I want to code Chinese SIP more flexible(use Model-View–ViewModel pattern), but I got a bottleneck. Could you explain how to create keyboard buttons programmatically(not to code in xaml) more detail?

  • aleeb

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by aleeb on Aug 03, 2011 21:39

    I get the same error: Xap packaging failed. I checked, the version is 7.0

     

  • aleeb

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by aleeb on Aug 03, 2011 22:09

    I could resolve the error: It has to do with the Background.jpg file. It has to be set to Resource, Do not copy. And when checking in the WMAppManifest.xml, make sure:

    <

     

    BackgroundImageURI IsRelative="true" IsResource="false">Background.jpg</BackgroundImageURI>

     

     

     

     

    (the extension must be .jpg, I think it might have been .png in my WMAppManifest).

    Clean and Rebuild worked after that.

     

  • verinder

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by verinder on Oct 14, 2011 23:23

    Hi,

    Thanks a ton for showing this implementation to me. I want to create a Punjabi Keyboard. Is it possible to switch to keyboard language for which windows phone 7 doesn't support font yet? I have font files for Punjabi language in desktop. Can you give me some more background on how to do this part.

  • rokie29

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by rokie29 on Mar 15, 2013 08:37

    Idk but sounds tight and id so get it

     

  • saumil

    Re: Windows Phone 7–Creating Custom Keyboard


    posted by saumil on Sep 02, 2013 12:30
    when i tried this code,it didn't work it shows error in keboardcontext error

Add Comment

Login to comment:
  *      *