Toggle keyboard using keyboard hook

This is transfered from my static page:

KeyToggle

Using function keys by pressing numbers. Written for ITC 700 color running windows mobile 2003.

Note: Updated KeyToggle.exe and download cab:
[Download not found]

There was a bug, so the sticky key still produced wm_keydown messages. Fixed version is v2.1.1.0.

With keytoggle you can define a ‘sticky’ key that will change the behaviour of the number keys. As long as the sticky key is ‘active’, number keys from 1 to 0 will produce the function keys F1 to F10. If sticky key is active, the left LED will light in green.

To start keytoggle just tap it or let it start by a link in StartUp. If keytoggle is loaded, you can see a small yellow arrow sign in the taskbar or on today screen.

keytoggle

If you tap this symbol, you are asked, if you want to unload the app. If the registry does not have values defined for keytoggle, it will use default values. If you try to launch keytoggle a second time you will get a message box. Only one instance of keytoggle can run at a time.

Using the registry you can define the behaviour of the sticky key. In example, you can have the sticky key remain active until it is pressed again, let it ‘go off’ or ‘fallback’ after a period of time or let it fallback after a number key has been pressed. If the sticky key is pressed again, it will always fallback.

REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Intermec\KeyToggle]
"Timeout"=dword:00000000
"autoFallback"=dword:00000001
"StickyKey"=dword:00000090

The values:

    StickyKey:
    default “144”, decimal (VK_NUMLOCK)
    the VK_ value of the sticky key. Here you define, what you will have as the sticky key. VK_ values are defined as in winuser.h. In example the VK_ value for the NumLock key is 0x90 (144 decimal, see VK_NUMLOCK). The sticky key will be consumed by keytoggle and is not visible to the system any more. That means, that you should choose key value that you do not need in any app you use.Timeout:
    default “3”, three seconds
    number of seconds the sticky key will remain active. If 0, the sticky key will not fallback automatically by time

    autoFallback:
    default “0”
    if 0 the sticky key will not fallback after pressing a number key. If 1 the sticky key will fallback after a number key is pressed

Launch arguments

    Keytoggle only supports one argument: “-writereg”. This will create the registry keys used by keytoggle and fill them with the default values.

The central code inside KeyToggle

// The command below tells the OS that this EXE has an export function so we can use the global hook without a DLL
__declspec(dllexport) LRESULT CALLBACK g_LLKeyboardHookCallback(
   int nCode,      // The hook code
   WPARAM wParam,  // The window message (WM_KEYUP, WM_KEYDOWN, etc.)
   LPARAM lParam   // A pointer to a struct with information about the pressed key
)
{
	/*	typedef struct {
	    DWORD vkCode;
	    DWORD scanCode;
	    DWORD flags;
	    DWORD time;
	    ULONG_PTR dwExtraInfo;
	} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/

	// Get out of hooks ASAP; no modal dialogs or CPU-intensive processes!
	// UI code really should be elsewhere, but this is just a test/prototype app
	// In my limited testing, HC_ACTION is the only value nCode is ever set to in CE
	static int iActOn = HC_ACTION;
	TCHAR str[MAX_PATH];
	PKBDLLHOOKSTRUCT pkbhData = (PKBDLLHOOKSTRUCT)lParam;
	DWORD vKey;
	if (nCode == iActOn)
	{
#ifdef DEBUG
			wsprintf(str, L"vkCode=\t0x%0x \n", pkbhData->vkCode);
			DEBUGMSG(true,(str));
			wsprintf(str, L"scanCode=\t0x%0x \n", pkbhData->scanCode);
			DEBUGMSG(true,(str));
			wsprintf(str, L"flags=\t0x%0x \n", pkbhData->flags);
			DEBUGMSG(true,(str));
			wsprintf(str, L"isStickyOn is=\t0x%0x \n", isStickyOn);
			DEBUGMSG(true,(str));
#endif
		//only process unflagged keys
		if (pkbhData->flags != 0x00)
			return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);

		//only process these types
		if ((wParam == WM_KEYUP) || (wParam == WM_KEYDOWN) || (wParam == WM_CHAR))
		{
			//dont care about sticky key down. v2.1.1
			if  (
				(pkbhData->vkCode == vkSticky) &&
				(wParam == WM_KEYDOWN)
				)
			{
				return -1;
			}

			//if num active change numeric keys to function keys
			//if sticky key set isStickyOn to active and start a timer to reset num after 3 seconds
			if  (
				(pkbhData->vkCode == vkSticky) &&
				(isStickyOn==false) &&
				(wParam == WM_KEYUP)
				)
			{
				LedOn(LEDid,1);
				isStickyOn=true;
				//start a timer
				if (stickyTimeout!=0)
					tID=SetTimer(NULL, 0, stickyTimeout, (TIMERPROC)Timer2Proc);
				return -1;
			}
			//if isStickyOn and sticky key is again pressed, toggle isStickyOn to OFF
			if ((pkbhData->vkCode == vkSticky) && (isStickyOn==true) && (wParam == WM_KEYUP))
			{
				LedOn(LEDid,0);
				isStickyOn=false;
				//start a timer
				if (stickyTimeout!=0)
					KillTimer(NULL, tID);
				return -1;
			}

			if ((isStickyOn==true) && (pkbhData->vkCode >= 0x30) && (pkbhData->vkCode <= 0x39)) 			{ 				//number key pressed and isStickyOn is active 				//get the pressed key 				vKey=pkbhData->vkCode;
				switch (vKey)
				{
					case 0x30: //0->F10
						vKey=VK_F10;
						break;
					default:
						vKey+=0x3F;//1 is 0x31, convert to F1 is 0x70
						break;
				}

				//create a new key event
				if (wParam == WM_KEYDOWN)
					keybd_event((byte)vKey, 0, KEYEVENTF_SILENT, 0); //key_down
				if (wParam == WM_KEYUP)
					keybd_event((byte)vKey, 0, KEYEVENTF_KEYUP |  KEYEVENTF_SILENT, 0); //key_up
				wsprintf(str, L"old Key=0x%0x -> new vkCode=\t0x%0x \n", pkbhData->vkCode, vKey);
				DEBUGMSG(true,(str));
				if ((autoFallback==1) && (wParam == WM_KEYUP)) //if autofallback
				{
					LedOn(LEDid,0);
					isStickyOn=false;
					if (stickyTimeout!=0)
						KillTimer(NULL, tID);
				}
				return -1;
			}
		}
	}
	return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}

Usage Sample Scenario

You have a ITC 700 Color device. This has a alphanumeric keyboard but no function keys. You need the function keys to be able to use a web application within iBrowse. With keytoggle you can now for example use the Gold key as sticky key. You have to download the keyboard remapper tool cpkbdmap.cab from the ITC site (keyboard remapping tool is part of ITC device Resource Kit) and assign the Gold key to NUMLOCK.

cpkbdmap

With this remapping and keytoggle running you will to get a function keystroke simulated if you press the Gold key and then a number key.

Source Code (eVC4, WM2003)

[Download not found]