iHookIE6
This small tool enables you to use Function keys within Internet Explorer Mobile (IEM) web sites.
Normally, most function keys are caught and used by the OS (GWES) to perform special actions like menu softkeys, phone call, end phone, volume up, volume down and more.
Using a keyboard hook, we can catch the function key presses, or better say WM_KEYDOWN
and WM_KEYUP
messages before the OS can catch them.
One challenge was to find the window that processes normal key presses. The keyboard Windows messages are not send to the top level window. Using the Remote Spy Tool, I found the Window inside Internet Explorer window that finally processes keyboard messages. Now the tool can hook the keyboard, catch F key presses (F1 to F24) and send them directly to the browser window (class name = “Internet Explorer_Server
”). The tool simply uses FindWindow
and GetWindow
to locate the window handle of this window and then does a PostMessage
with WM_KEYDOWN
and WM_KEYUP
directly to the browser window.
The hook function is as given below:
__declspec(dllexport) LRESULT CALLBACK g_LLKeyboardHookCallback(
int nCode, WPARAM wParam, LPARAM lParam )
{
static int iActOn = HC_ACTION;
bool processed_key=false;
int iResult=0;
if (nCode == iActOn)
{
HWND hwndBrowserComponent=getIEMBrowserWindow(); if(getIEMWindow(&iResult)==NULL || hwndBrowserComponent==NULL)
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
PKBDLLHOOKSTRUCT pkbhData = (PKBDLLHOOKSTRUCT)lParam;
if(pkbhData->vkCode >= VK_F1 && pkbhData->vkCode <=VK_F24){
DEBUGMSG(1,(L"found function key 0x%08x ...\n", pkbhData->vkCode));
if(processed_key==false){
if (wParam == WM_KEYUP)
{
DEBUGMSG(1,(L"posting WM_KEYUP 0x%08x to 0x%08x, lParam=0x%08x...\n",
pkbhData->vkCode, hwndBrowserComponent, g_lparamCodeUp[pkbhData->vkCode - 0x70]));
PostMessage(hwndBrowserComponent, WM_KEYUP, pkbhData->vkCode,
g_lparamCodeUp[pkbhData->vkCode - 0x70]);
processed_key=true;
}
else if (wParam == WM_KEYDOWN)
{
DEBUGMSG(1,(L"posting WM_KEYDOWN 0x%08x to 0x%08x, lParam=0x%08x...\n",
pkbhData->vkCode, hwndBrowserComponent,
g_lparamCodeDown[pkbhData->vkCode - 0x70]));
PostMessage(hwndBrowserComponent, WM_KEYDOWN, pkbhData->vkCode,
g_lparamCodeDown[pkbhData->vkCode - 0x70]);
processed_key=true;
}
}
}
}
else
DEBUGMSG(1, (L"Got unknown action code: 0x%08x\n", nCode));
if (processed_key)
{
processed_key=false; if (bForwardKey){
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
else
return true;
}
else
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
You will see that the web site code in IEM can now process these function key presses using the body onKeyDown
event.
The browser window with a JavaScript key demo:
(See also onkey.htm in http://www.hjgode.de/wp/2009/05/14/internet-explorer-mobile-handles-key-events/)
The same will not work, if you switched the browser engine from IE6 (or MSHTML) to PocketIE
using the HKLM\Security\Internet Explorer\MSHTML="0"
entry.
The screenshot shows that function keys are sent to the browser window. But you will see no reaction inside the web site.
Only the newer engine, started with Windows Mobile AKU 6.1.4, supports keyboard events inside the JavaScript object model.
To find the browser window, you normally would use EnumChildWindows()
, but this API is not available on Windows CE based devices. So I re-used some code to scan a window for child and sibling windows to find the nested browser window:
static BOOL bStopScan=FALSE;
BOOL scanWindow(HWND hWndStart, TCHAR* szClass){
HWND hWnd = NULL;
HWND hWnd1 = NULL;
hWnd = hWndStart;
TCHAR cszWindowString [MAX_PATH]; TCHAR cszClassString [MAX_PATH]; TCHAR cszTemp [MAX_PATH]; BOOL bRet=FALSE;
while (hWnd!=NULL && !bStopScan){
GetClassName(hWnd, cszClassString, MAX_PATH);
GetWindowText(hWnd, cszWindowString, MAX_PATH);
wsprintf(cszTemp, L"\"%s\" \"%s\"\t0x%08x\n",
cszClassString, cszWindowString, hWnd); if(wcsicmp(cszClassString, szClass)==0){
DEBUGMSG(1 , (L"\n################### found target window, hwnd=0x%08x\n\n", hWnd));
g_hWndIEM6=hWnd; hWnd=NULL;
hWndStart=NULL;
bRet=TRUE;
bStopScan=TRUE;
return TRUE; }
hWnd1 = GetWindow(hWnd, GW_CHILD);
if( hWnd1 != NULL ){
scanWindow(hWnd1, szClass);
}
hWnd=GetWindow(hWnd,GW_HWNDNEXT); }
return bRet;
}
Thanks to all the code providers on the internet, keep coding and publishing.
You could download iHookIE6_v20120927.zip - VS2008 source code, WM5 SDK, DEBUG binary.