- Added kbsdll to install hooks (does not work on ReactOS). To switch layouts temporarily used keys Left Alt + F10

svn path=/trunk/; revision=33607
This commit is contained in:
Dmitry Chapyshev 2008-05-20 12:53:31 +00:00
parent 14f90f0f92
commit 0f37c3c8f0
7 changed files with 288 additions and 21 deletions

View file

@ -0,0 +1,127 @@
/*
* PROJECT: ReactOS Keyboard Layout Switcher
* FILE: kbswitch/kbsdll/kbsdll.c
* PROGRAMMER: Dmitry Chapyshev <dmitry@reactos.org>
*
*/
#include "../kbswitch.h"
HHOOK hKeyboardHook, hLangHook, hWinHook;
HINSTANCE hInstance;
HWND hKbSwitchWnd;
static VOID
SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
{
PostMessage(hKbSwitchWnd, Msg, wParam, lParam);
}
/* Not used yet */
LRESULT CALLBACK
KeyboardHookProc(int code, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(hKeyboardHook, code, wParam, lParam);
}
LRESULT CALLBACK
LangHookProc(int code, WPARAM wParam, LPARAM lParam)
{
PMSG msg;
msg = (PMSG) lParam;
switch (msg->message)
{
case WM_INPUTLANGCHANGEREQUEST:
{
SendMessageToMainWnd(WM_LANG_CHANGED, wParam, msg->lParam);
}
break;
case WM_HOTKEY:
{
if (msg->hwnd)
{
SendMessageToMainWnd(WM_LOAD_LAYOUT, (WPARAM)msg->hwnd, msg->lParam);
}
}
break;
}
return CallNextHookEx(hLangHook, code, wParam, lParam);
}
LRESULT CALLBACK
WinHookProc(int code, WPARAM wParam, LPARAM lParam)
{
int id = GlobalAddAtom(_T("KBSWITCH"));
switch (code)
{
case HCBT_SETFOCUS:
{
if ((HWND)wParam != NULL)
{
if ((HWND)wParam != hKbSwitchWnd)
{
SendMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
}
}
}
break;
case HCBT_CREATEWND:
{
RegisterHotKey((HWND)wParam, id, MOD_ALT, VK_F10);
}
break;
case HCBT_DESTROYWND:
{
UnregisterHotKey((HWND)wParam, id);
}
break;
}
GlobalDeleteAtom(id);
return CallNextHookEx(hWinHook, code, wParam, lParam);
}
BOOL
KbSwitchSetHooks()
{
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProc, hInstance, 0);
hLangHook = SetWindowsHookEx(WH_GETMESSAGE, LangHookProc, hInstance, 0);
hWinHook = SetWindowsHookEx(WH_CBT, WinHookProc, hInstance, 0);
if ((hKeyboardHook)&&(hLangHook)&&(hWinHook))
return TRUE;
else
return FALSE;
}
VOID
KbSwitchDeleteHooks()
{
if (hKeyboardHook) UnhookWindowsHookEx(hKeyboardHook);
if (hLangHook) UnhookWindowsHookEx(hLangHook);
if (hWinHook) UnhookWindowsHookEx(hWinHook);
}
BOOL WINAPI
DllMain(IN HINSTANCE hinstDLL,
IN DWORD dwReason,
IN LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
hInstance = hinstDLL;
hKbSwitchWnd = FindWindow(szKbSwitcherName, NULL);
if (!hKbSwitchWnd) return FALSE;
break;
}
return TRUE;
}

View file

@ -0,0 +1,7 @@
LIBRARY kbsdll.dll
EXPORTS
KbSwitchSetHooks
KbSwitchDeleteHooks
; EOF

View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
<module name="kbsdll" type="win32dll" baseaddress="0x74720000" installbase="system32" installname="kbsdll.dll" unicode="yes">
<importlibrary definition="kbsdll.def" />
<include base="kbsdll">.</include>
<define name="_WIN32_IE">0x0500</define>
<define name="_WIN32_WINNT">0x0600</define>
<define name="WINVER">0x0600</define>
<library>ntdll</library>
<library>kernel32</library>
<library>user32</library>
<library>comctl32</library>
<file>kbsdll.c</file>
<file>kbsdll.rc</file>
</module>

View file

@ -0,0 +1,8 @@
#include <windows.h>
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Keyboard Layout Switcher\0"
#define REACTOS_STR_INTERNAL_NAME "kbsdll\0"
#define REACTOS_STR_ORIGINAL_FILENAME "kbsdll.dll\0"
#include <reactos/version.rc>

View file

@ -10,7 +10,8 @@
#define WM_NOTIFYICONMSG (WM_USER + 248)
TCHAR szKbSwitcherName[] = _T("kbswitcher");
PROC KbSwitchSetHooks = NULL;
PROC KbSwitchDeleteHooks = NULL;
static BOOL
@ -21,6 +22,8 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName);
HINSTANCE hInst;
HANDLE hProcessHeap;
HMODULE hDllLib;
ULONG ulCurrentLayoutNum = 1;
static HICON
CreateTrayIcon(LPTSTR szLCID)
@ -135,7 +138,7 @@ UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = hwnd;
tnid.uID = 1;
tnid.uFlags = NIF_ICON | NIF_MESSAGE |NIF_TIP;
tnid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
tnid.hIcon = CreateTrayIcon(szLCID);
@ -189,6 +192,16 @@ GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID)
return TRUE;
}
VOID
GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID)
{
/*
FIXME!!! This way of getting layout ID incorrect!
This will not work correctly for 0001040a, 00010410, etc
*/
wsprintf(szLayoutID, _T("00000%x"), LOWORD(hKl));
}
static BOOL
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
{
@ -258,7 +271,7 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
BOOL CALLBACK
EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
SendMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
return TRUE;
}
@ -278,8 +291,10 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum)
// Switch to the new keyboard layout
UpdateTrayIcon(hwnd, szLCID, szName);
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDWININICHANGE);
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
ulCurrentLayoutNum = uLayoutNum;
}
static HMENU
@ -360,18 +375,101 @@ BuildRightPopupMenu()
return hMenu;
}
BOOL
SetHooks()
{
hDllLib = LoadLibrary(_T("kbsdll.dll"));
if (!hDllLib) return FALSE;
KbSwitchSetHooks = (PROC) GetProcAddress(hDllLib, MAKEINTRESOURCEA(1));
KbSwitchDeleteHooks = (PROC) GetProcAddress(hDllLib, MAKEINTRESOURCEA(2));
if ((KbSwitchSetHooks == NULL)||(KbSwitchDeleteHooks == NULL))
return FALSE;
return KbSwitchSetHooks();
}
VOID
DeleteHooks()
{
if (KbSwitchDeleteHooks) KbSwitchDeleteHooks();
if (hDllLib) FreeLibrary(hDllLib);
}
BOOL CALLBACK
EnumChildProc(HWND hwnd, LPARAM lParam)
{
SendMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
return TRUE;
}
ULONG
GetNextLayout()
{
TCHAR szLayoutNum[3 + 1], szLayoutID[CCH_LAYOUT_ID + 1];
ULONG Ret = ulCurrentLayoutNum;
_ultot(ulCurrentLayoutNum, szLayoutNum, 10);
if (!GetLayoutID(szLayoutNum, szLayoutID))
{
return -1;
}
_ultot(Ret + 1, szLayoutNum, 10);
if (GetLayoutID(szLayoutNum, szLayoutID))
{
return (Ret + 1);
}
else
{
_ultot(Ret - 1, szLayoutNum, 10);
if (GetLayoutID(szLayoutNum, szLayoutID))
return (Ret - 1);
else
return -1;
}
return -1;
}
LRESULT CALLBACK
WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
static HMENU hLeftPopupMenu, hRightPopupMenu;
static TCHAR szLCID[MAX_PATH];
switch (Message)
{
case WM_CREATE:
{
SetHooks();
AddTrayIcon(hwnd);
hLeftPopupMenu = BuildLeftPopupMenu(hwnd);
hRightPopupMenu = BuildRightPopupMenu(hwnd);
break;
}
break;
case WM_LANG_CHANGED:
{
GetLayoutIDByHkl((HKL)lParam, szLCID);
UpdateTrayIcon(hwnd, szLCID, _T(""));
}
break;
case WM_LOAD_LAYOUT:
{
ActivateLayout(hwnd, GetNextLayout());
}
break;
case WM_WINDOW_ACTIVATE:
{
GetLayoutIDByHkl(GetKeyboardLayout(GetWindowThreadProcessId((HWND)wParam, 0)), szLCID);
UpdateTrayIcon(hwnd, szLCID, _T(""));
}
break;
case WM_NOTIFYICONMSG:
switch (lParam)
@ -388,8 +486,8 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
else
TrackPopupMenu(hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
PostMessage(hwnd, WM_NULL, 0, 0);
break;
}
break;
}
break;
@ -412,9 +510,8 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
if (!ShellExecuteEx(&shInputDll))
MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_OK | MB_ICONERROR);
break;
}
break;
default:
ActivateLayout(hwnd, LOWORD(wParam));
@ -428,15 +525,18 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
//FIXME: Should detect default language changes by CPL applet or by other tools and update UI
}
}
break;
}
break;
case WM_DESTROY:
{
DeleteHooks();
DestroyMenu(hLeftPopupMenu);
DestroyMenu(hRightPopupMenu);
DelTrayIcon(hwnd);
PostQuitMessage(0);
break;
}
break;
}
return DefWindowProc(hwnd, Message, wParam, lParam);

View file

@ -11,3 +11,10 @@
// Maximum Character Count of a ULONG in decimal
#define CCH_ULONG_DEC 10
#define WM_KEY_PRESSED (WM_USER + 10100)
#define WM_LANG_CHANGED (WM_USER + 10200)
#define WM_WINDOW_ACTIVATE (WM_USER + 10300)
#define WM_LOAD_LAYOUT (WM_USER + 10400)
TCHAR szKbSwitcherName[] = _T("kbswitcher");

View file

@ -1,13 +1,16 @@
<?xml version="1.0"?>
<group xmlns:xi="http://www.w3.org/2001/XInclude">
<module name="kbswitch" type="win32gui" installbase="system32" installname="kbswitch.exe" unicode="yes">
<include base="kbswitch">.</include>
<library>kernel32</library>
<library>advapi32</library>
<library>user32</library>
<library>shell32</library>
<library>gdi32</library>
<file>kbswitch.c</file>
<file>kbswitch.rc</file>
</module>
<module name="kbswitch" type="win32gui" installbase="system32" installname="kbswitch.exe" unicode="yes">
<include base="kbswitch">.</include>
<library>kernel32</library>
<library>advapi32</library>
<library>user32</library>
<library>shell32</library>
<library>gdi32</library>
<file>kbswitch.c</file>
<file>kbswitch.rc</file>
</module>
<directory name="kbsdll">
<xi:include href="kbsdll/kbsdll.rbuild" />
</directory>
</group>