Click here to Skip to main content
15,885,216 members
Articles / Desktop Programming / MFC

Virtual On-Screen Keyboard Example

Rate me:
Please Sign up or sign in to vote.
4.21/5 (11 votes)
15 Jan 2009CPOL2 min read 95.9K   7.5K   28   11
A simple MFC dialog-based framework that mimics the behavior of the MS On-Screen Keyboard.

Introduction

A dialog can send key input to any foreground window without itself being activated to function as an on-screen keyboard. Regular windows get activated and focused when they are clicked or something. To avoid this, a window needs to be a non-activating window. You can do this by creating a window with the "WS_EX_NOACTIVATE" extended style, or by modifying its style using "ModifyStyleEx". But, with this style, a window behaves somewhat differently than expected when you move the window. To solve this, you need to provide your own implementations for the "WM_NCLBUTTONDOWN" and "WM_MOUSEMOVE" messages to behave the same way as the system-provided On-Screen Keyboard does. This code shows how to do this and send your own keyboard inputs to any foreground window using the newly-introduced "SendInput" system function.

Background

One day, I needed to implement a virtual On-Screen Keyboard that received signals - through a COM (serial) port - from a custom input device and then sent keyboard inputs to the system according to the signals. While doing this, I came to know about the On-Screen Keyboard accessory application provided by Windows, and wanted my application to behave similar to that. But, it was not as trivial a task as I first expected, because of the "focus" and "activation" problems. In this example, you will find that avoiding those problems could be done in a simple way.

Using the code

This is a VC++ 9.0 project.

Firstly, you need to create an MFC dialog-based application. And then, to make the dialog a non-activating topmost window, you need to change its "No Activate" and "Topmost" resource properties to "true".

Then, handle "WM_NCLBUTTONDOWN" message. This is for making the dialog temporarily behave as a regular window without the "WS_EX_NOACTIVATE" style so that it can move smoothly.

C++
void COnScreenKeyboardDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
 if (!m_hForegroundWnd)
 {
  // store current foreground window
  m_hForegroundWnd = ::GetForegroundWindow();
  // temporarily make this dialog an activatable window
  ModifyStyleEx(WS_EX_NOACTIVATE,0);
  // make this dialog foreground
  SetForegroundWindow();
 }
 CDialog::OnNcLButtonDown(nHitTest, point);
}

Now, handle the "WM_MOVE" message. This is for making the dialog behave again as a non-activating window when the mouse pointer moves around in the client area, and for making any previous foreground window active. This is the exact behavior the system-provided On-Screen Keyboard shows.

C++
void COnScreenKeyboardDlg::OnMouseMove(UINT nFlags, CPoint point)
{
 if (m_hForegroundWnd)
 {
  // make the previous foreground window active
  ::SetForegroundWindow(m_hForegroundWnd);
  // make this dialog non-activating
  ModifyStyleEx(0,WS_EX_NOACTIVATE);
  // set it to NULL to mark that we do not need to do this again
  m_hForegroundWnd = NULL;
 }
 CDialog::OnMouseMove(nFlags, point);
}

Now, to send an arbitrary key input to the system, you can use the "SendInput" function. Here, I send the "x" (virtual code 88) key input as an example when the "Send X" button in the dialog is clicked.

C++
void COnScreenKeyboardDlg::OnBnClickedSendX()
{
 INPUT keyInput;
 keyInput.type = INPUT_KEYBOARD;
 KEYBDINPUT key;
 key.wVk = 88;
 key.wScan = ::VkKeyScan(88);
 key.dwFlags = 0;
 keyInput.ki = key;
 ::SendInput(1,&keyInput,sizeof(INPUT));
 key.dwFlags = KEYEVENTF_KEYUP;
 keyInput.ki = key;
 ::SendInput(1,&keyInput,sizeof(INPUT));
}

Points of interest

Code samples I have found on the Internet do this in an overly complicated manner using the "AttachThreadInput" function. As you can see, making a window behave the same way as the Windows On-Screen Keyboard can be done in a simple way using the "WS_EX_NOACTIVATE" style and some other small tricks.

License

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


Written By
Korea (Republic of) Korea (Republic of)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionIts Difference between "Windows7 On-screen Keyboard" vs "This Project" Pin
Member 1279463714-Oct-16 20:19
Member 1279463714-Oct-16 20:19 
Generalqibord Pin
vimal_nsit28-Jun-16 17:04
vimal_nsit28-Jun-16 17:04 
QuestionVirtual On-Screen Keyboard Pin
Member 1148555915-Mar-15 9:14
Member 1148555915-Mar-15 9:14 
Questionajka454 Pin
ajka45413-Jan-14 22:33
professionalajka45413-Jan-14 22:33 
GeneralThis is quite useful Pin
v!cky29-Sep-13 5:38
v!cky29-Sep-13 5:38 
QuestionNeed help to port web based G7 onscreen-keypad to Windows Native application. Pin
Member 815507611-Aug-12 1:26
Member 815507611-Aug-12 1:26 
Generalvirtual on screen keyboard Pin
shriisha20-Jun-09 2:44
shriisha20-Jun-09 2:44 
QuestionCan key logger read your keys when you press button down? Pin
Member 352977719-Jun-09 8:35
Member 352977719-Jun-09 8:35 
GeneralIt was somewhat buggy. Here goes the correction. Pin
visubong16-Jan-09 3:50
visubong16-Jan-09 3:50 
GeneralRe: It was somewhat buggy. Here goes the correction. Pin
bnnkyw17-Apr-11 16:50
bnnkyw17-Apr-11 16:50 
GeneralVirtual On-Screen Keyboard Example Pin
snprani15-Jan-09 20:02
snprani15-Jan-09 20:02 

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.