mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 19:05:52 +00:00
- 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:
parent
14f90f0f92
commit
0f37c3c8f0
7 changed files with 288 additions and 21 deletions
127
reactos/base/applications/kbswitch/kbsdll/kbsdll.c
Normal file
127
reactos/base/applications/kbswitch/kbsdll/kbsdll.c
Normal 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;
|
||||||
|
}
|
7
reactos/base/applications/kbswitch/kbsdll/kbsdll.def
Normal file
7
reactos/base/applications/kbswitch/kbsdll/kbsdll.def
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
LIBRARY kbsdll.dll
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
KbSwitchSetHooks
|
||||||
|
KbSwitchDeleteHooks
|
||||||
|
|
||||||
|
; EOF
|
15
reactos/base/applications/kbswitch/kbsdll/kbsdll.rbuild
Normal file
15
reactos/base/applications/kbswitch/kbsdll/kbsdll.rbuild
Normal 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>
|
8
reactos/base/applications/kbswitch/kbsdll/kbsdll.rc
Normal file
8
reactos/base/applications/kbswitch/kbsdll/kbsdll.rc
Normal 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>
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
||||||
|
|
||||||
TCHAR szKbSwitcherName[] = _T("kbswitcher");
|
PROC KbSwitchSetHooks = NULL;
|
||||||
|
PROC KbSwitchDeleteHooks = NULL;
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
|
@ -21,6 +22,8 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName);
|
||||||
|
|
||||||
HINSTANCE hInst;
|
HINSTANCE hInst;
|
||||||
HANDLE hProcessHeap;
|
HANDLE hProcessHeap;
|
||||||
|
HMODULE hDllLib;
|
||||||
|
ULONG ulCurrentLayoutNum = 1;
|
||||||
|
|
||||||
static HICON
|
static HICON
|
||||||
CreateTrayIcon(LPTSTR szLCID)
|
CreateTrayIcon(LPTSTR szLCID)
|
||||||
|
@ -135,7 +138,7 @@ UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
|
||||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||||
tnid.hWnd = hwnd;
|
tnid.hWnd = hwnd;
|
||||||
tnid.uID = 1;
|
tnid.uID = 1;
|
||||||
tnid.uFlags = NIF_ICON | NIF_MESSAGE |NIF_TIP;
|
tnid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
||||||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||||
tnid.hIcon = CreateTrayIcon(szLCID);
|
tnid.hIcon = CreateTrayIcon(szLCID);
|
||||||
|
|
||||||
|
@ -189,6 +192,16 @@ GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID)
|
||||||
return TRUE;
|
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
|
static BOOL
|
||||||
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
||||||
{
|
{
|
||||||
|
@ -258,7 +271,7 @@ GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName)
|
||||||
BOOL CALLBACK
|
BOOL CALLBACK
|
||||||
EnumWindowsProc(HWND hwnd, LPARAM lParam)
|
EnumWindowsProc(HWND hwnd, LPARAM lParam)
|
||||||
{
|
{
|
||||||
SendMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
|
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,8 +291,10 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum)
|
||||||
// Switch to the new keyboard layout
|
// Switch to the new keyboard layout
|
||||||
UpdateTrayIcon(hwnd, szLCID, szName);
|
UpdateTrayIcon(hwnd, szLCID, szName);
|
||||||
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
||||||
SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDWININICHANGE);
|
|
||||||
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
|
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
|
||||||
|
|
||||||
|
ulCurrentLayoutNum = uLayoutNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HMENU
|
static HMENU
|
||||||
|
@ -360,18 +375,101 @@ BuildRightPopupMenu()
|
||||||
return hMenu;
|
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
|
LRESULT CALLBACK
|
||||||
WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static HMENU hLeftPopupMenu, hRightPopupMenu;
|
static HMENU hLeftPopupMenu, hRightPopupMenu;
|
||||||
|
static TCHAR szLCID[MAX_PATH];
|
||||||
|
|
||||||
switch (Message)
|
switch (Message)
|
||||||
{
|
{
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
|
{
|
||||||
|
SetHooks();
|
||||||
AddTrayIcon(hwnd);
|
AddTrayIcon(hwnd);
|
||||||
hLeftPopupMenu = BuildLeftPopupMenu(hwnd);
|
hLeftPopupMenu = BuildLeftPopupMenu(hwnd);
|
||||||
hRightPopupMenu = BuildRightPopupMenu(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:
|
case WM_NOTIFYICONMSG:
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
|
@ -388,8 +486,8 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
else
|
else
|
||||||
TrackPopupMenu(hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
|
TrackPopupMenu(hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
|
||||||
PostMessage(hwnd, WM_NULL, 0, 0);
|
PostMessage(hwnd, WM_NULL, 0, 0);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -412,9 +510,8 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
if (!ShellExecuteEx(&shInputDll))
|
if (!ShellExecuteEx(&shInputDll))
|
||||||
MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_OK | MB_ICONERROR);
|
MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_OK | MB_ICONERROR);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ActivateLayout(hwnd, LOWORD(wParam));
|
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
|
//FIXME: Should detect default language changes by CPL applet or by other tools and update UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
|
{
|
||||||
|
DeleteHooks();
|
||||||
DestroyMenu(hLeftPopupMenu);
|
DestroyMenu(hLeftPopupMenu);
|
||||||
DestroyMenu(hRightPopupMenu);
|
DestroyMenu(hRightPopupMenu);
|
||||||
DelTrayIcon(hwnd);
|
DelTrayIcon(hwnd);
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProc(hwnd, Message, wParam, lParam);
|
return DefWindowProc(hwnd, Message, wParam, lParam);
|
||||||
|
|
|
@ -11,3 +11,10 @@
|
||||||
|
|
||||||
// Maximum Character Count of a ULONG in decimal
|
// Maximum Character Count of a ULONG in decimal
|
||||||
#define CCH_ULONG_DEC 10
|
#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");
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||||
<module name="kbswitch" type="win32gui" installbase="system32" installname="kbswitch.exe" unicode="yes">
|
<module name="kbswitch" type="win32gui" installbase="system32" installname="kbswitch.exe" unicode="yes">
|
||||||
<include base="kbswitch">.</include>
|
<include base="kbswitch">.</include>
|
||||||
<library>kernel32</library>
|
<library>kernel32</library>
|
||||||
<library>advapi32</library>
|
<library>advapi32</library>
|
||||||
<library>user32</library>
|
<library>user32</library>
|
||||||
<library>shell32</library>
|
<library>shell32</library>
|
||||||
<library>gdi32</library>
|
<library>gdi32</library>
|
||||||
<file>kbswitch.c</file>
|
<file>kbswitch.c</file>
|
||||||
<file>kbswitch.rc</file>
|
<file>kbswitch.rc</file>
|
||||||
</module>
|
</module>
|
||||||
|
<directory name="kbsdll">
|
||||||
|
<xi:include href="kbsdll/kbsdll.rbuild" />
|
||||||
|
</directory>
|
||||||
</group>
|
</group>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue