Hello Windows Mobile Users! Recently, the following was requested: How can I start an application by just hitting some keys in sequence? The answer: Just use a keyboard hook.
So I started to code this hook tool based on my KeyToggleBoot2
code. There was not too much to change. The new tool is called KeyToggleStart
and it is configured by the Registry:
REGEDIT4
[HKEY_LOCAL_MACHINE\Software\Intermec\KeyToggleStart]
"ForbiddenKeys"=hex:\
72 73 00
;max 10 keys!
"KeySeq"="123"
"Timeout"=dword:00000003
"LEDid"=dword:00000001
"Exe"="\\Windows\\iexplore.exe"
"Arg"=""
Reg Keys Meaning
Forbiddenkeys
is just an add-on feature: key codes entered in this list will not be processed any more by your Windows Mobile device. For example, to disable the use of the F3 (VK_TTALK
) and F4 (VK_TEND
) keys, you have to enter a binary list of 0×72,0×73,0×00 (the zero is needed to terminate the list).
KeySeq
lists the char
sequence you want to use to start an application. For example, if this is the string
“123
″, every time you enter 123
in sequence within the given time, the application defined will be started.
TimeOut
is the time in seconds you have to enter the sequence. So do not use a long key sequence as “starteiexplorenow
” and a short timeout (except if you are a very fast type writer). The timeout is started with the first char
matching and ends after the time or when you enter a non-matching char
of the sequence.
With LEDid
, you can specify a LED index number. LEDs on Windows Mobile are controlled by an index number, each LED has one or more ID assigned to it. So, with LEDid
, you can control which LED will lit, when the matching process is running. You can even find an ID to control a vibration motor, if your Windows Mobile device is equipped with one.
The Exe
registry string
value is used to specify which application will be started when the key sequence is matched.
If the application you want to be started needs some arguments, you can enter these using the Arg
registry value.
When you start the KeyToggleStart
tool, you will not see any window except for a notification symbol on your Start/Home screen of the device.
If you tap this icon (redirection sign), you have the chance to end the hook tool.
The code itself is nothing special. Only the sequence matching code is a little bit special. As the char
s in the sequence do not match keystrokes in a one-to-one manner, I have to check the shift state of the keyboard and if the current char
of the sequence is a char
needing a shift. For example: the asterisk char
(“*
”) is a combination of the “8
″ key plus the Shift key. So, if you have the “*
” in the char
sequence, the code has to check for the “8
″ key and if the keyboard is in shift state:
__declspec(dllexport) LRESULT CALLBACK g_LLKeyboardHookCallback(
int nCode, WPARAM wParam, LPARAM lParam )
{
static int iActOn = HC_ACTION;
static bool isShifted=false;
#ifdef DEBUG
static TCHAR str[MAX_PATH];
#endif
PKBDLLHOOKSTRUCT pkbhData = (PKBDLLHOOKSTRUCT)lParam;
if (nCode == iActOn)
{
if (pkbhData->flags != 0x00)
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
if(pForbiddenKeyList!=NULL)
{
BOOL bForbidden=false;
int j=0;
do{
if(pForbiddenKeyList[j]==(BYTE)pkbhData->vkCode)
{
bForbidden=true;
DEBUGMSG(1, (L"suppressing forbidden key: 0x%0x\n",pkbhData->vkCode));
continue;
}
j++;
}while(!bForbidden && pForbiddenKeyList[j]!=0x00);
if(bForbidden){
return true;
}
}
SHORT sShifted = GetAsyncKeyState(VK_SHIFT);
if((sShifted & 0x800) == 0x800)
isShifted = true;
else
isShifted = false;
if (pkbhData->vkCode == VK_SHIFT){
DEBUGMSG(1, (L"Ignoring VK_SHIFT\n"));
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
if ((byte)pkbhData->vkCode == (byte)szVKeySeq[iMatched]){
DEBUGMSG(1 , (L"==== char match\n"));
if (bCharShiftSeq[iMatched] == isShifted){
DEBUGMSG(1 , (L"==== shift match\n"));
}
else{
DEBUGMSG(1 , (L"==== shift not match\n"));
}
}
if( wParam == WM_KEYUP ){
DEBUGMSG(1, (L"---> szVKeySeq[iMatched] = 0x%02x\n", (byte)szVKeySeq[iMatched]));
if ( ((byte)pkbhData->vkCode == (byte)szVKeySeq[iMatched]) &&
(isShifted == bCharShiftSeq[iMatched]) ) {
if(iMatched==0){
LedOn(LEDid,1);
tID=SetTimer(NULL, 0, matchTimeout, (TIMERPROC)Timer2Proc);
}
iMatched++;
DEBUGMSG(1, (L"iMatched is now=%i\n", iMatched));
if (iMatched == iKeyCount){
DEBUGMSG(1, (L"FULL MATCH, starting ...\n"));
PostMessage(g_hWnd, WM_SHOWMYDIALOG, 0, 0);
DEBUGMSG(1, (L"FULL MATCH: Reset matching\n"));
LedOn(LEDid,0);
iMatched=0; KillTimer(NULL, tID);
}
}
else
{
KillTimer(NULL, tID);
LedOn(LEDid,0);
iMatched=0; DEBUGMSG(1, (L"FULL MATCH missed. Reseting matching\n"));
}
} }
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
Enjoy the code!