Introduction
The company where I work has a number of products where user is prompted for
a password or other type of security code. The
recent $420 million scam involving keylogger
spooked everybody, so we started looking at alternative technologies to secure
access to sensitive data. Although some of these technologies are quite expensive,
it occurred to me that there was a cheap alternative to keyboard entry
that would be simple to implement: an on-screen keyboard, where user
enters a password by clicking on keys that are displayed on a virtual keyboard.
The easiest way to explain is to show you what I mean:
Windows XP:
Windows 2000:
XKeyboard Features
XKeyboard offers following features:
-
All keyboard characters - The two Shift buttons are toggle buttons
implemented using my
CXButtonXP
class.
This allows access to all characters
available on a real keyboard, including special characters.
For ease of use, Shift keys on real keyboard also cause the
XKeyboard keys to be shifted.
-
Show plain text - The user can display plain text of password:
-
Minimum/maximum password length - You can specify how long password must be.
-
Most recently used (MRU) passwords - You can specify a list of passwords that have
been recently used. A password that is similar to any of the passwords in list
will be rejected. The virtual function
CheckMRUPasswords()
allows you to
customize algorithm used to determine similarity.
-
Dialog timeout - You can specify a timeout for dialog, which will force it to close
after timeout expires. This will prevent possibility of leaving dialog open, with
a password in edit control. In case of timeout, dialog returns code
IDABORT
.
-
Read-only edit control - You can specify that edit control should be read-only.
If not read-only, user may enter a password by typing on real keyboard, which
somewhat defeats the purpose.
-
Upper/lower case - You can specify to convert password to upper or lower case,
or leave it unchanged.
-
Special characters - You can specify that password should include special
characters, digits, or just alphanumeric characters. The virtual function
CheckSpecial()
allows you to
customize algorithm used to determine whether password contains special characters.
-
String resources - all messages displayed by XKeyboard are
contained in string resources.
-
Spacebar - You can specify to display spacebar. Not displaying spacebar
means that spaces will not be allowed in password (even if edit control
is not read-only). When spacebar is not displayed, the dialog is resized:
CXKeyboard Implementation Notes
As you can see from code, there is nothing special about
XKeyboard. It
is implemented as a dialog with buttons for usual keyboard keys. Pressing either
Shift key toggles upper/lower case (and in this case, also toggles the
special characters to "shifted" character).
One decision I made was to not use a checkbox button (in "push-like" mode).
I didn't like the way button behaved on XP with theming - when you push
it, it immediately pops back to display a non-pushed state, until you move the
cursor off button, when it displays a pushed state. So I used my
new XButtonXP control instead.
XKeyboard uses two timers; one timer is used if there is timeout set, and
the other timer is used to check if shift keys on real keyboard
are pressed. Pressing either real shift key works just as you would expect - as
long as real shift key is held down, XKeyboard shows shifted
character set. When real shift key is released, XKeyboard shows unshifted
character set.
CXKeyboard API
The
CXKeyboard
API includes:
GetPassword() | Returns the password |
SetPassword() | Sets the edit control with password |
GetShowText() | Returns state of Show Text checkbox |
SetShowText() | Sets state of Show Text checkbox |
GetShowSpacebar() | Returns TRUE if spacebar is visible |
SetShowSpacebar() | Sets visibility of spacebar (TRUE = visible) |
GetSpecial() | Returns enum value of special character setting |
SetSpecial() | Sets special character enum value |
GetMinLength() | Returns minimum length of a password |
SetMinLength() | Sets minimum length of password |
GetMaxLength() | Returns minimum length of a password |
SetMaxLength() | Sets minimum length of password |
GetCase() | Returns enum value of case setting |
SetCase() | Sets case enum value |
SetMRUPasswords() | Sets MRU password list |
ClearMRUPasswords() | Clears MRU password list |
GetTimeout() | Returns timeout value in seconds |
SetTimeout() | Sets timeout value in seconds; 0 = no timeout |
GetReadOnly() | Returns read-only state of edit control |
SetReadOnly() | Sets read-only state of edit control (TRUE = read-only) |
CheckSpecial() | Virtual function that returns TRUE if password contains a special character |
CheckMRUPasswords() | Virtual function that returns TRUE if password is in MRU list |
How to use
To integrate CXKeyboard
into your app, you first need to add following files to your project:
- XKeyboard.cpp
- XKeyboard.h
- XKeyboardRes.h
- XKeyboard.rc
- XButtonXP.cpp
- XButtonXP.h
- XThemeHelper.cpp
- XThemeHelper.h
- OddButton.cpp
- OddButton.h
- MemDC.h
You also need to add XKeyboard.rc to your project's rc file - go
to View | Resource Includes... and in bottom listbox, scroll down to end.
Insert #include "XKeyboard.rc"
right before #endif
:
Next, include header file XKeyboard.h in appropriate project files.
Now you are ready to start using CXKeyboard
.
Compiler Prerequisites
XKeyboard requires the
Platform SDK to compile. If you get a compile error about
DFCS_HOT
being
undefined, you should include the following line in
stdafx.h, before any header file includes:
#define WINVER 0x0500
Calling XKeyboard
The demo app shows how to call
XKeyboard:
CStringArray sa;
sa.Add(_T("qwer"));
sa.Add(_T("asdf"));
sa.Add(_T("zxcv"));
CPoint point;
GetCursorPos(&point);
CXKeyboard dlg(point.x, point.y-247);
dlg.SetShowText(m_bShowText);
dlg.SetMRUPasswords(sa);
int n = _ttoi(m_strMinLength);
if (n <= 0)
n = 1;
dlg.SetMinLength(n);
dlg.SetMaxLength(_ttoi(m_strMaxLength));
dlg.SetTimeout(_ttoi(m_strTimeout));
dlg.SetSpecial((CXKeyboard::SPECIAL_CHARACTERS)m_nSpecial);
dlg.SetShowSpacebar(m_bShowSpacebar);
dlg.SetCase((CXKeyboard::XKEYBOARD_CASE)m_nCase);
dlg.SetPassword(m_strPassword);
int rc = dlg.DoModal();
if (rc == IDOK)
{
m_strPassword = dlg.GetPassword();
m_bShowText = dlg.GetShowText();
GetDlgItem(IDC_STATUS)->SetWindowText(m_strPassword);
}
else if (rc == IDABORT)
{
GetDlgItem(IDC_STATUS)->SetWindowText(_T("Dialog timed out"));
}
else
{
GetDlgItem(IDC_STATUS)->SetWindowText(_T("Dialog cancelled by user"));
}
Other On-Screen Keyboard Implementations
There is a Microsoft on-screen keyboard
(Programs | Accessories | Accessibility) that is shipped
with Win2k and XP. Microsoft licensed this product from
Madentec Limited.
Click-N-Type is a freeware on-screen keyboard that is very popular.
Both of these products are available only as standalone executables, although
the Madentec site mentions that an SDK is available.
Revision History
Version 1.0 - 2005 April 4
Usage
This software is released into the public domain. You are free to use it in any way
you like, except that you may not sell this source code. If you modify it or extend it,
please to consider posting new code here for everyone to share. This software is provided
"as is" with no expressed or implied warranty. I accept no liability for any damage or
loss of business that this software may cause.