mirror of
https://github.com/reactos/reactos.git
synced 2026-05-07 23:36:33 +08:00
[KBSWITCH] Make Alt+Shift working Part 1 (#8039)
Recently language switching (Alt+Shift) was not working. This PR will fix Alt+Shift (partially). JIRA issue: CORE-18546 - Add WH_KEYBOARD_LL hook to detect Alt+Shift. - Add delay to the action after language change. - Increase g_SpecialIds not to be full. - Delete useless ID_NEXTLAYOUT command.
This commit is contained in:
committed by
GitHub
parent
c03d7794b8
commit
3df71d678d
@@ -1,14 +1,17 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Keyboard Layout Switcher
|
||||
* FILE: base/applications/kbswitch/kbsdll/kbsdll.c
|
||||
* PROGRAMMER: Dmitry Chapyshev <dmitry@reactos.org>
|
||||
*
|
||||
* PROJECT: ReactOS Keyboard Layout Switcher
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Switching Keyboard Layouts
|
||||
* COPYRIGHT: Copyright Dmitry Chapyshev (dmitry@reactos.org)
|
||||
* Copyright Colin Finck (mail@colinfinck.de)
|
||||
* Copyright 2022-2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#include "../kbswitch.h"
|
||||
|
||||
HHOOK hWinHook = NULL;
|
||||
HHOOK hShellHook = NULL;
|
||||
HHOOK hKeyboardLLHook = NULL;
|
||||
HINSTANCE hInstance = NULL;
|
||||
HWND hKbSwitchWnd = NULL;
|
||||
|
||||
@@ -18,77 +21,108 @@ PostMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
PostMessage(hKbSwitchWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
WinHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
static LRESULT CALLBACK
|
||||
WinHookProc(INT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (code < 0)
|
||||
{
|
||||
return CallNextHookEx(hWinHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case HCBT_ACTIVATE:
|
||||
case HCBT_SETFOCUS:
|
||||
{
|
||||
HWND hwndFocus = (HWND)wParam;
|
||||
if (hwndFocus && hwndFocus != hKbSwitchWnd)
|
||||
{
|
||||
PostMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
|
||||
}
|
||||
PostMessageToMainWnd(WM_WINDOW_ACTIVATE, (WPARAM)hwndFocus, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallNextHookEx(hWinHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
ShellHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
static LRESULT CALLBACK
|
||||
ShellHookProc(INT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (code < 0)
|
||||
{
|
||||
return CallNextHookEx(hShellHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case HSHELL_WINDOWACTIVATED:
|
||||
{
|
||||
PostMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, 0);
|
||||
break;
|
||||
}
|
||||
case HSHELL_LANGUAGE:
|
||||
{
|
||||
PostMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallNextHookEx(hShellHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
KbSwitchSetHooks(VOID)
|
||||
static LRESULT CALLBACK
|
||||
KeyboardLLHook(INT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
hWinHook = SetWindowsHookEx(WH_CBT, WinHookProc, hInstance, 0);
|
||||
hShellHook = SetWindowsHookEx(WH_SHELL, ShellHookProc, hInstance, 0);
|
||||
if (code < 0)
|
||||
return CallNextHookEx(hKeyboardLLHook, code, wParam, lParam);
|
||||
|
||||
if (!hWinHook || !hShellHook)
|
||||
if (code == HC_ACTION)
|
||||
{
|
||||
return FALSE;
|
||||
KBDLLHOOKSTRUCT *pKbStruct = (KBDLLHOOKSTRUCT *)lParam;
|
||||
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
|
||||
{
|
||||
BOOL bShiftPressed = GetAsyncKeyState(VK_SHIFT) < 0;
|
||||
BOOL bAltPressed = GetAsyncKeyState(VK_MENU) < 0;
|
||||
BOOL bCtrlPressed = GetAsyncKeyState(VK_CONTROL) < 0;
|
||||
// Detect Alt+Shift and Ctrl+Shift
|
||||
if ((pKbStruct->vkCode == VK_SHIFT && bAltPressed) ||
|
||||
(pKbStruct->vkCode == VK_MENU && bShiftPressed) ||
|
||||
(pKbStruct->vkCode == VK_SHIFT && bCtrlPressed) ||
|
||||
(pKbStruct->vkCode == VK_CONTROL && bShiftPressed))
|
||||
{
|
||||
PostMessageToMainWnd(WM_LANG_CHANGED, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return CallNextHookEx(hKeyboardLLHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
KbSwitchDeleteHooks(VOID)
|
||||
BOOL APIENTRY
|
||||
KbSwitchSetHooks(_In_ BOOL bDoHook)
|
||||
{
|
||||
if (hWinHook)
|
||||
if (bDoHook)
|
||||
{
|
||||
UnhookWindowsHookEx(hWinHook);
|
||||
hWinHook = NULL;
|
||||
hWinHook = SetWindowsHookEx(WH_CBT, WinHookProc, hInstance, 0);
|
||||
hShellHook = SetWindowsHookEx(WH_SHELL, ShellHookProc, hInstance, 0);
|
||||
hKeyboardLLHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardLLHook, hInstance, 0);
|
||||
|
||||
if (hWinHook && hShellHook && hKeyboardLLHook)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Unhook */
|
||||
if (hKeyboardLLHook)
|
||||
{
|
||||
UnhookWindowsHookEx(hKeyboardLLHook);
|
||||
hKeyboardLLHook = NULL;
|
||||
}
|
||||
if (hShellHook)
|
||||
{
|
||||
UnhookWindowsHookEx(hShellHook);
|
||||
hShellHook = NULL;
|
||||
}
|
||||
if (hWinHook)
|
||||
{
|
||||
UnhookWindowsHookEx(hWinHook);
|
||||
hWinHook = NULL;
|
||||
}
|
||||
return !bDoHook;
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
@@ -103,9 +137,7 @@ DllMain(IN HINSTANCE hinstDLL,
|
||||
hInstance = hinstDLL;
|
||||
hKbSwitchWnd = FindWindow(szKbSwitcherName, NULL);
|
||||
if (!hKbSwitchWnd)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
1 stdcall KbSwitchSetHooks()
|
||||
2 stdcall KbSwitchDeleteHooks()
|
||||
1 stdcall KbSwitchSetHooks(long)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/*
|
||||
* PROJECT: Keyboard Layout Switcher
|
||||
* FILE: base/applications/kbswitch/kbswitch.c
|
||||
* PURPOSE: Switching Keyboard Layouts
|
||||
* PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
|
||||
* Colin Finck (mail@colinfinck.de)
|
||||
* Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
* PROJECT: ReactOS Keyboard Layout Switcher
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Switching Keyboard Layouts
|
||||
* COPYRIGHT: Copyright Dmitry Chapyshev (dmitry@reactos.org)
|
||||
* Copyright Colin Finck (mail@colinfinck.de)
|
||||
* Copyright 2022-2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#include "kbswitch.h"
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
@@ -32,12 +31,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(internat);
|
||||
|
||||
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
||||
|
||||
PKBSWITCHSETHOOKS KbSwitchSetHooks = NULL;
|
||||
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks = NULL;
|
||||
#define TIMER_ID_LANG_CHANGED_DELAYED 0x10000
|
||||
#define TIMER_LANG_CHANGED_DELAY 200
|
||||
|
||||
FN_KbSwitchSetHooks KbSwitchSetHooks = NULL;
|
||||
UINT ShellHookMessage = 0;
|
||||
|
||||
HINSTANCE hInst;
|
||||
HANDLE hProcessHeap;
|
||||
HINSTANCE g_hInst = NULL;
|
||||
HMODULE g_hHookDLL = NULL;
|
||||
INT g_nCurrentLayoutNum = 1;
|
||||
HICON g_hTrayIcon = NULL;
|
||||
@@ -45,8 +45,8 @@ HWND g_hwndLastActive = NULL;
|
||||
INT g_cKLs = 0;
|
||||
HKL g_ahKLs[64];
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
/* Debug logging */
|
||||
ULONG NTAPI
|
||||
vDbgPrintExWithPrefix(IN PCCH Prefix,
|
||||
IN ULONG ComponentId,
|
||||
IN ULONG Level,
|
||||
@@ -54,27 +54,24 @@ vDbgPrintExWithPrefix(IN PCCH Prefix,
|
||||
IN va_list ap)
|
||||
{
|
||||
CHAR Buffer[512];
|
||||
|
||||
SIZE_T PrefixLength = strlen(Prefix);
|
||||
strncpy(Buffer, Prefix, PrefixLength);
|
||||
|
||||
_vsnprintf(Buffer + PrefixLength,
|
||||
sizeof(Buffer) - PrefixLength,
|
||||
Format,
|
||||
ap);
|
||||
|
||||
_vsnprintf(Buffer + PrefixLength, _countof(Buffer) - PrefixLength, Format, ap);
|
||||
Buffer[_countof(Buffer) - 1] = ANSI_NULL; /* Avoid buffer overrun */
|
||||
OutputDebugStringA(Buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
typedef struct tagSPECIAL_ID
|
||||
{
|
||||
DWORD dwLayoutId;
|
||||
HKL hKL;
|
||||
TCHAR szKLID[CCH_LAYOUT_ID + 1];
|
||||
} SPECIAL_ID, *PSPECIAL_ID;
|
||||
|
||||
SPECIAL_ID g_SpecialIds[80];
|
||||
#define MAX_SPECIAL_IDS 256
|
||||
|
||||
SPECIAL_ID g_SpecialIds[MAX_SPECIAL_IDS];
|
||||
INT g_cSpecialIds = 0;
|
||||
|
||||
static VOID LoadSpecialIds(VOID)
|
||||
@@ -121,7 +118,7 @@ static VOID LoadSpecialIds(VOID)
|
||||
|
||||
if (g_cSpecialIds >= _countof(g_SpecialIds))
|
||||
{
|
||||
OutputDebugStringA("g_SpecialIds is full!");
|
||||
ERR("g_SpecialIds is full!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -158,16 +155,20 @@ GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
|
||||
}
|
||||
}
|
||||
|
||||
static HKL GetActiveKL(VOID)
|
||||
{
|
||||
/* FIXME: Get correct console window's HKL when console window */
|
||||
HWND hwndTarget = (g_hwndLastActive ? g_hwndLastActive : GetForegroundWindow());
|
||||
DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||
return GetKeyboardLayout(dwTID);
|
||||
}
|
||||
|
||||
static VOID UpdateLayoutList(HKL hKL OPTIONAL)
|
||||
{
|
||||
INT iKL;
|
||||
|
||||
if (!hKL)
|
||||
{
|
||||
HWND hwndTarget = (g_hwndLastActive ? g_hwndLastActive : GetForegroundWindow());
|
||||
DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||
hKL = GetKeyboardLayout(dwTID);
|
||||
}
|
||||
hKL = GetActiveKL();
|
||||
|
||||
g_cKLs = GetKeyboardLayoutList(_countof(g_ahKLs), g_ahKLs);
|
||||
|
||||
@@ -191,15 +192,9 @@ static VOID UpdateLayoutList(HKL hKL OPTIONAL)
|
||||
static HKL GetHKLFromLayoutNum(INT nLayoutNum)
|
||||
{
|
||||
if (0 <= (nLayoutNum - 1) && (nLayoutNum - 1) < g_cKLs)
|
||||
{
|
||||
return g_ahKLs[nLayoutNum - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND hwndTarget = (g_hwndLastActive ? g_hwndLastActive : GetForegroundWindow());
|
||||
DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||
return GetKeyboardLayout(dwTID);
|
||||
}
|
||||
return GetActiveKL();
|
||||
}
|
||||
|
||||
static VOID
|
||||
@@ -587,11 +582,9 @@ SetHooks(VOID)
|
||||
}
|
||||
|
||||
#define IHOOK_SET 1
|
||||
#define IHOOK_DELETE 2
|
||||
KbSwitchSetHooks = (PKBSWITCHSETHOOKS) GetProcAddress(g_hHookDLL, MAKEINTRESOURCEA(IHOOK_SET));
|
||||
KbSwitchDeleteHooks = (PKBSWITCHDELETEHOOKS) GetProcAddress(g_hHookDLL, MAKEINTRESOURCEA(IHOOK_DELETE));
|
||||
KbSwitchSetHooks = (FN_KbSwitchSetHooks)GetProcAddress(g_hHookDLL, MAKEINTRESOURCEA(IHOOK_SET));
|
||||
|
||||
if (!KbSwitchSetHooks || !KbSwitchDeleteHooks || !KbSwitchSetHooks())
|
||||
if (!KbSwitchSetHooks || !KbSwitchSetHooks(TRUE))
|
||||
{
|
||||
ERR("SetHooks failed\n");
|
||||
return FALSE;
|
||||
@@ -604,10 +597,10 @@ SetHooks(VOID)
|
||||
VOID
|
||||
DeleteHooks(VOID)
|
||||
{
|
||||
if (KbSwitchDeleteHooks)
|
||||
if (KbSwitchSetHooks)
|
||||
{
|
||||
KbSwitchDeleteHooks();
|
||||
KbSwitchDeleteHooks = NULL;
|
||||
KbSwitchSetHooks(FALSE);
|
||||
KbSwitchSetHooks = NULL;
|
||||
}
|
||||
|
||||
if (g_hHookDLL)
|
||||
@@ -654,20 +647,12 @@ UpdateLanguageDisplay(HWND hwnd, HKL hKL)
|
||||
}
|
||||
|
||||
HWND
|
||||
GetTargetWindow(HWND hwndFore)
|
||||
GetTargetWindow(HWND hwndFore OPTIONAL)
|
||||
{
|
||||
TCHAR szClass[64];
|
||||
HWND hwndIME;
|
||||
HWND hwndTarget = hwndFore;
|
||||
if (hwndTarget == NULL)
|
||||
hwndTarget = GetForegroundWindow();
|
||||
|
||||
GetClassName(hwndTarget, szClass, _countof(szClass));
|
||||
if (_tcsicmp(szClass, szKbSwitcherName) == 0)
|
||||
HWND hwndTarget = (hwndFore ? hwndFore : GetForegroundWindow());
|
||||
if (IsWndClassName(hwndTarget, szKbSwitcherName))
|
||||
hwndTarget = g_hwndLastActive;
|
||||
|
||||
hwndIME = ImmGetDefaultIMEWnd(hwndTarget);
|
||||
return (hwndIME ? hwndIME : hwndTarget);
|
||||
return hwndTarget;
|
||||
}
|
||||
|
||||
UINT
|
||||
@@ -682,26 +667,17 @@ UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
|
||||
|
||||
static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
|
||||
{
|
||||
TCHAR szClass[64];
|
||||
|
||||
hwndFore = GetAncestor(hwndFore, GA_ROOT);
|
||||
|
||||
if (!IsWindowVisible(hwndFore) || !GetClassName(hwndFore, szClass, _countof(szClass)))
|
||||
if (!IsWindowVisible(hwndFore))
|
||||
return FALSE;
|
||||
|
||||
if (_tcsicmp(szClass, szKbSwitcherName) == 0 ||
|
||||
_tcsicmp(szClass, TEXT("Shell_TrayWnd")) == 0)
|
||||
if (IsWndClassName(hwndFore, szKbSwitcherName) ||
|
||||
IsWndClassName(hwndFore, TEXT("Shell_TrayWnd")))
|
||||
{
|
||||
return FALSE; /* Special window */
|
||||
}
|
||||
|
||||
/* FIXME: CONWND needs special handling */
|
||||
if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
||||
{
|
||||
HKL hKL = GetKeyboardLayout(0);
|
||||
UpdateLanguageDisplay(hwnd, hKL);
|
||||
}
|
||||
|
||||
g_hwndLastActive = hwndFore;
|
||||
return TRUE;
|
||||
}
|
||||
@@ -734,19 +710,37 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
|
||||
case WM_TIMER:
|
||||
{
|
||||
TRACE("WM_LANG_CHANGED: wParam:%p, lParam:%p\n", wParam, lParam);
|
||||
UpdateLayoutList((HKL)lParam);
|
||||
UpdateLanguageDisplay(hwnd, (HKL)lParam);
|
||||
if (wParam == TIMER_ID_LANG_CHANGED_DELAYED)
|
||||
{
|
||||
KillTimer(hwnd, TIMER_ID_LANG_CHANGED_DELAYED);
|
||||
HKL hKL = GetActiveKL();
|
||||
UpdateLayoutList(hKL);
|
||||
UpdateLanguageDisplay(hwnd, hKL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// WM_LANG_CHANGED message:
|
||||
// wParam: HWND hwndTarget or zero
|
||||
// lParam: HKL hKL or zero
|
||||
case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
|
||||
{
|
||||
TRACE("WM_LANG_CHANGED: wParam:%p, lParam:%p\n", wParam, lParam);
|
||||
/* Delayed action */
|
||||
KillTimer(hwnd, TIMER_ID_LANG_CHANGED_DELAYED);
|
||||
SetTimer(hwnd, TIMER_ID_LANG_CHANGED_DELAYED, TIMER_LANG_CHANGED_DELAY, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
// WM_WINDOW_ACTIVATE message:
|
||||
// wParam: HWND hwndTarget or zero
|
||||
// lParam: zero
|
||||
case WM_WINDOW_ACTIVATE: /* Comes from kbsdll.dll and this module */
|
||||
{
|
||||
HWND hwndFore;
|
||||
TRACE("WM_WINDOW_ACTIVATE: wParam:%p, lParam:%p\n", wParam, lParam);
|
||||
hwndFore = GetForegroundWindow();
|
||||
HWND hwndFore = wParam ? (HWND)wParam : GetForegroundWindow();
|
||||
if (RememberLastActive(hwnd, hwndFore))
|
||||
return UpdateLanguageDisplayCurrent(hwnd, hwndFore);
|
||||
break;
|
||||
@@ -764,24 +758,29 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
GetCursorPos(&pt);
|
||||
SetForegroundWindow(hwnd);
|
||||
|
||||
INT nID;
|
||||
if (lParam == WM_LBUTTONUP)
|
||||
{
|
||||
/* Rebuild the left popup menu on every click to take care of keyboard layout changes */
|
||||
hLeftPopupMenu = BuildLeftPopupMenu();
|
||||
TrackPopupMenu(hLeftPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
|
||||
nID = TrackPopupMenu(hLeftPopupMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
|
||||
DestroyMenu(hLeftPopupMenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_hRightPopupMenu)
|
||||
{
|
||||
s_hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_POPUP));
|
||||
s_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_POPUP));
|
||||
s_hRightPopupMenu = GetSubMenu(s_hMenu, 0);
|
||||
}
|
||||
TrackPopupMenu(s_hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
|
||||
nID = TrackPopupMenu(s_hRightPopupMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
|
||||
}
|
||||
|
||||
PostMessage(hwnd, WM_NULL, 0, 0);
|
||||
|
||||
if (nID)
|
||||
PostMessage(hwnd, WM_COMMAND, nID, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -807,46 +806,6 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_NEXTLAYOUT:
|
||||
{
|
||||
HWND hwndTarget = (HWND)lParam, hwndTargetSave = NULL;
|
||||
DWORD dwThreadID;
|
||||
HKL hKL;
|
||||
UINT uNum;
|
||||
TCHAR szClass[64];
|
||||
BOOL bCONWND = FALSE;
|
||||
|
||||
if (hwndTarget == NULL)
|
||||
hwndTarget = g_hwndLastActive;
|
||||
|
||||
/* FIXME: CONWND needs special handling */
|
||||
if (hwndTarget &&
|
||||
GetClassName(hwndTarget, szClass, _countof(szClass)) &&
|
||||
_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
||||
{
|
||||
bCONWND = TRUE;
|
||||
hwndTargetSave = hwndTarget;
|
||||
hwndTarget = NULL;
|
||||
}
|
||||
|
||||
if (hwndTarget)
|
||||
{
|
||||
dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||
hKL = GetKeyboardLayout(dwThreadID);
|
||||
uNum = GetLayoutNum(hKL);
|
||||
if (uNum != 0)
|
||||
g_nCurrentLayoutNum = uNum;
|
||||
}
|
||||
|
||||
ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
|
||||
|
||||
/* FIXME: CONWND needs special handling */
|
||||
if (bCONWND)
|
||||
ActivateLayout(hwnd, g_nCurrentLayoutNum, hwndTargetSave, TRUE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (1 <= LOWORD(wParam) && LOWORD(wParam) <= 1000)
|
||||
@@ -866,7 +825,7 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (wParam == SPI_SETNONCLIENTMETRICS)
|
||||
{
|
||||
PostMessage(hwnd, WM_WINDOW_ACTIVATE, wParam, lParam);
|
||||
PostMessage(hwnd, WM_WINDOW_ACTIVATE, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -874,6 +833,7 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
case WM_DESTROY:
|
||||
{
|
||||
KillTimer(hwnd, TIMER_ID_LANG_CHANGED_DELAYED);
|
||||
DeleteHooks();
|
||||
DestroyMenu(s_hMenu);
|
||||
DeleteTrayIcon(hwnd);
|
||||
@@ -893,9 +853,9 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TRACE("ShellHookMessage: wParam:%p, lParam:%p\n", wParam, lParam);
|
||||
if (wParam == HSHELL_LANGUAGE)
|
||||
PostMessage(hwnd, WM_LANG_CHANGED, wParam, lParam);
|
||||
else if (wParam == HSHELL_WINDOWACTIVATED)
|
||||
PostMessage(hwnd, WM_WINDOW_ACTIVATE, wParam, lParam);
|
||||
PostMessage(hwnd, WM_LANG_CHANGED, 0, 0);
|
||||
else if (wParam == HSHELL_WINDOWACTIVATED || wParam == HSHELL_RUDEAPPACTIVATED)
|
||||
PostMessage(hwnd, WM_WINDOW_ACTIVATE, 0, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -938,8 +898,7 @@ _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdSh
|
||||
return 1;
|
||||
}
|
||||
|
||||
hInst = hInstance;
|
||||
hProcessHeap = GetProcessHeap();
|
||||
g_hInst = hInstance;
|
||||
|
||||
ZeroMemory(&WndClass, sizeof(WndClass));
|
||||
WndClass.lpfnWndProc = WndProc;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winuser.h>
|
||||
@@ -14,17 +14,26 @@
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
// Character Count of a layout ID like "00000409"
|
||||
#define CCH_LAYOUT_ID 8
|
||||
#define CCH_LAYOUT_ID 8 // Character Count of a layout ID like "00000409"
|
||||
#define CCH_ULONG_DEC 10 // Maximum Character Count of a ULONG in decimal
|
||||
|
||||
// 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)
|
||||
|
||||
typedef BOOL (WINAPI *PKBSWITCHSETHOOKS) (VOID);
|
||||
typedef VOID (WINAPI *PKBSWITCHDELETEHOOKS) (VOID);
|
||||
typedef BOOL (APIENTRY *FN_KbSwitchSetHooks)(BOOL bDoHook);
|
||||
|
||||
const TCHAR szKbSwitcherName[] = INDICATOR_CLASS;
|
||||
|
||||
static inline BOOL
|
||||
IsWndClassName(_In_opt_ HWND hwndTarget, PCTSTR pszName)
|
||||
{
|
||||
TCHAR szClass[32];
|
||||
GetClassName(hwndTarget, szClass, _countof(szClass));
|
||||
return lstrcmpi(szClass, pszName) == 0;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
IsConsoleWnd(_In_opt_ HWND hwndTarget)
|
||||
{
|
||||
return IsWndClassName(hwndTarget, TEXT("ConsoleWindowClass"));
|
||||
}
|
||||
|
||||
@@ -9,4 +9,3 @@
|
||||
/* Menu items */
|
||||
#define ID_EXIT 10001
|
||||
#define ID_PREFERENCES 10002
|
||||
#define ID_NEXTLAYOUT 10003
|
||||
|
||||
Reference in New Issue
Block a user