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

Virtual On-Screen Keyboard Example

, 15 Jan 2009
Rate this:
Please Sign up or sign in to vote.
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.

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.

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.

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)

Share

About the Author

visubong

Korea (Republic Of) Korea (Republic Of)
No Biography provided

Comments and Discussions

 
Questionajka454 Pinprofessionalajka45413-Jan-14 22:33 
GeneralThis is quite useful Pinmemberv!cky29-Sep-13 5:38 
QuestionNeed help to port web based G7 onscreen-keypad to Windows Native application. [modified] PinmemberMember 815507611-Aug-12 1:26 
Generalvirtual on screen keyboard Pinmembershriisha20-Jun-09 2:44 
QuestionCan key logger read your keys when you press button down? PinmemberMember 352977719-Jun-09 8:35 
GeneralIt was somewhat buggy. Here goes the correction. Pinmembervisubong16-Jan-09 3:50 
GeneralRe: It was somewhat buggy. Here goes the correction. Pinmemberbnnkyw17-Apr-11 16:50 
GeneralVirtual On-Screen Keyboard Example Pinmembersnprani15-Jan-09 20:02 

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.140826.1 | Last Updated 15 Jan 2009
Article Copyright 2009 by visubong
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid