Click here to Skip to main content
15,566,394 members
Articles / Programming Languages / XML
Posted 9 Aug 2021


15 bookmarked

Customized Onscreen Keyboard in C#

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
11 Aug 2021CPOL4 min read
Customized onscreen keyboard in C# for Windows
I had built onscreen keyboards for several software applications, but I had never made one full-fledged keyboard with 101+ keys. So, I decided to tackle this project and build my onscreen keyboard in C#. In this article, I have shared my approach and the source code, so you will have a starting point if you wish to continue.


If you have ever built software for touchscreen devices, you know that having an onscreen keyboard is an essential component. Windows comes with an Onscreen keyboard as one of its built-in Ease of Access tools.
Windows OSK is a solution, but you don’t have much control over its functions and behavior, let alone building new tasks to it!

In this article, I show what are the basic methods to build an onscreen keyboard for Windows and customize it.


I had built onscreen keyboards for several software applications, but I had never made one full-fledged keyboard with 101+ keys. In a recent project, we needed a complete onscreen keyboard to be included and we can control it.

So, I ended working on this project and what you see here is the results of my work. You can expand it and build it to suit your needs.

The Key Method

The “key” to build your Onscreen Keyboard, is to use SendKeys.Send method:


This method sends keystrokes to the active application. For example, if you want to click a button and send the TAB keystroke, you use the following method:


If your request does not represent valid keystrokes, you will get an ArgumentException in your code.


  1. Sometimes, you need to send more than one character to get a specific key.

    For example, to specify the open parentheses sign, use “{{}”.

  2. The plus sign (+), caret (^), percent sign (%), tilde (~), and parentheses () have special meanings to SendKeys. To specify one of these characters, enclose it within braces ({}).
  3. To specify characters that aren’t displayed when you press a key, such as ENTER or TAB, and keys that represent actions rather than characters, you must use specific codes.

For example:

SendKeys.Send("{MULTIPLY}"); //The Multiply key on the number keypad
SendKeys.Send("{ADD}");      //The Add key on the number keypad

Handling SHIFT, CTRL, and ALT

Combination keys, such as CTRL + Key, SHIFT + Key, and ALT + Key, are possible by using caret (^), plus(+), and percent sign (%).

To specify to hold down CTRL while S is pressed, followed by D without SHIFT, use “^SD”.

To specify to hold down SHIFT and press A and B, use “+(AB)”.

SendKeys.Send("^({F10})"); //CTRL + F10
SendKeys.Send("+({F10})"); //Shift + F10
SendKeys.Send("%({F10})"); //ALT + F10

Planning the Keyboard Layout

I decided to go by the layout of my physical keyboard:

Physical Keyboard

I opened a new C# Winforms with the .NET Framework project in Visual Studio.
I added my keys, according to the physical keyboard layout:

Onscreen Keyboard layout

For the majority of the keys, you can use a button control, except for these special keys, which need to be CheckBox controls:


So, when the CAPSLOCK key is in the on mode, you have a checked CheckBox that identifies capital letters. CAPSLOCK off creates keystrokes for lowercase letters.

For keys with two characters, such as 2 (@) or 7 (&), we have to check the status of the SHIFT button and generate the proper keystroke accordingly.

SHIFT + 2 should send @ sign.

Similar situations apply to the combination keys such as CTRL + C (Copy), CTRL + P (Paste), and so on.

Image 3

if (capslock.Checked || lshift.Checked || rshift.Checked)
SendKeys.Send("B"); lshift.Checked = false; rshift.Checked = false; 
else { 

To identify when any of the checkboxes are in a checked state, I use background color:

if (capslock.Checked == true) 
   capslock.BackColor = System.Drawing.ColorTranslator.FromHtml("#0076D7"); 
   capslock.BackColor = System.Drawing.ColorTranslator.FromHtml("#333333");

Custom Keys

Now that I have complete control of my onscreen keyboard, I want to add custom keys. Imagine Custom keys as a shortcut to send two or more characters in one keystroke.

Image 4

Some more cosmetic details include adding a row with CAPS, Insert, and NUM LOCK key status. I change the visibility of the labels for CAPS and NUM depends on the On or Off status of the corresponding keys. I also added the code to change the background color of the keys as you hover the mouse over them.

Image 5

Border Style Issue

If you select the None option from your form properties for the FormBorderStyle, you will not be able to move your keyboard around the screen and change its position.

If you don’t mind the standard Windows border, you can choose an option that best fits your taste and usage of your keyboard.

I wanted to get rid of the border and have my border style. So this is what I have done:

  1. I set the FormBorderStyle to None
  2. Placed all my keys to a panel, which is sitting on the main form
  3. Changed the form’s background color to create a contrast with the panel’s background color

Now I have my colors and make-shift border, but how can I move my onscreen keyboard?

The trick here requires a Win32 API:

[DllImportAttribute("user32.dll")] public static extern int SendMessage
                                   (IntPtr hWnd, int Msg, int wParam, int lParam); 
[DllImportAttribute("user32.dll")] public static extern bool ReleaseCapture();
private void Form1_MouseDown(object sender, MouseEventArgs e)
 if (e.Button == MouseButtons.Left) 
    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); 


I have an onscreen keyboard with customized background and border style, which I can move around the screen and add custom keys to it.

Points of Interest

As I was working on this project, I came up with so many ideas to expand the normal onscreen keyboard to something much more. The Custom keys was one that I implemented in this code.


  • 9th August, 2021: First release of this code

I hope to get another chance to work on this project again, and perhaps port it to Xamarin.


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

Written By
Chief Technology Officer
United States United States
I sold my beloved racing bicycle to buy my first computer, a Sinclair home computer! That was over 30 years ago and I am still in love with what became my profession, and quite honestly my calling! I have received my BS and MS in Mathematics and Computer science and have been working in so many fields of software development, system architecture, and design and I have most enjoyed teaching and writing about programming languages and fiddling with new technologies!
I believe life is too short to ignore learning a programming language!

Comments and Discussions

SuggestionYour solution file appears to contain missing project Pin
Thomas Nielsen - getCore25-Jul-22 9:44
professionalThomas Nielsen - getCore25-Jul-22 9:44 
QuestionWer da codez? Pin
tonyhicks2010-Aug-21 22:07
tonyhicks2010-Aug-21 22:07 
AnswerRe: Wer da codez? Pin
Kourosh K Tari11-Aug-21 18:54
Kourosh K Tari11-Aug-21 18:54 
QuestionWhere is the code? Pin
Salam Y. ELIAS10-Aug-21 3:25
professionalSalam Y. ELIAS10-Aug-21 3:25 
AnswerRe: Where is the code? Pin
Kourosh K Tari11-Aug-21 18:56
Kourosh K Tari11-Aug-21 18:56 
QuestionSource code? Pin
giulicard10-Aug-21 3:14
giulicard10-Aug-21 3:14 
It will certainly be a great job, but I'm curious to see the code. Years ago I wrote an onscreen keyboard in C # for an embedded application, si I would like to see how you have solved the puzzle.

If you are interested in my keyboard source code, which automatically manage international layouts, is here [^]

AnswerRe: Source code? Pin
Kourosh K Tari11-Aug-21 18:58
Kourosh K Tari11-Aug-21 18:58 
QuestionNo code ? Pin
Alex (RSA)10-Aug-21 0:47
professionalAlex (RSA)10-Aug-21 0:47 
AnswerRe: No code ? Pin
Kourosh K Tari11-Aug-21 18:59
Kourosh K Tari11-Aug-21 18:59 

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.