mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[KBSWITCH][CPL:INPUT][NTUSER][EXPLORER] Fix keyboard layout icon (#4815)
Fix keyboard layout icon in taskbar notification area. JIRA issue: CORE-11700, CORE-2699, CORE-18546
- Call ActivateKeyboardLayout to select the keyboard layout correctly.
- Modify WM_INPUTLANGCHANGEREQUEST parameter.
- Modify BroadcastSystemMessageW parameter.
- Revert Taskbar Notification Area MA_NOACTIVATE HACK 8344291
. This fixes Context Menu display.
- Load the "IME File" value and set the IME icon if necessary.
- Correctly implement global hooks.
This commit is contained in:
parent
a06f10d0c0
commit
36f7d1a953
8 changed files with 318 additions and 71 deletions
|
@ -2,7 +2,7 @@
|
|||
add_rc_deps(kbswitch.rc ${CMAKE_CURRENT_SOURCE_DIR}/res/kbswitch.ico)
|
||||
add_executable(kbswitch kbswitch.c kbswitch.rc)
|
||||
set_module_type(kbswitch win32gui UNICODE)
|
||||
add_importlibs(kbswitch advapi32 user32 shell32 gdi32 msvcrt kernel32)
|
||||
add_importlibs(kbswitch advapi32 imm32 user32 shell32 gdi32 msvcrt kernel32)
|
||||
add_cd_file(TARGET kbswitch DESTINATION reactos/system32 FOR all)
|
||||
|
||||
add_subdirectory(kbsdll)
|
||||
|
|
|
@ -13,7 +13,7 @@ HINSTANCE hInstance = NULL;
|
|||
HWND hKbSwitchWnd = NULL;
|
||||
|
||||
static VOID
|
||||
SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
PostMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PostMessage(hKbSwitchWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
@ -21,36 +21,40 @@ SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
|
|||
LRESULT CALLBACK
|
||||
WinHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int id = GlobalAddAtom(_T("KBSWITCH"));
|
||||
if (code < 0)
|
||||
{
|
||||
return CallNextHookEx(hWinHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case HCBT_SETFOCUS:
|
||||
{
|
||||
if ((HWND)wParam != NULL)
|
||||
HWND hwndFocus = (HWND)wParam;
|
||||
if (hwndFocus && hwndFocus != hKbSwitchWnd)
|
||||
{
|
||||
if ((HWND)wParam != hKbSwitchWnd)
|
||||
{
|
||||
SendMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
|
||||
}
|
||||
PostMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
GlobalDeleteAtom(id);
|
||||
|
||||
return CallNextHookEx(hWinHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
ShellHookProc(int code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (code < 0)
|
||||
{
|
||||
return CallNextHookEx(hShellHook, code, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case HSHELL_LANGUAGE:
|
||||
{
|
||||
SendMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
|
||||
PostMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -75,8 +79,16 @@ KbSwitchSetHooks(VOID)
|
|||
VOID WINAPI
|
||||
KbSwitchDeleteHooks(VOID)
|
||||
{
|
||||
if (hWinHook) UnhookWindowsHookEx(hWinHook);
|
||||
if (hShellHook) UnhookWindowsHookEx(hShellHook);
|
||||
if (hWinHook)
|
||||
{
|
||||
UnhookWindowsHookEx(hWinHook);
|
||||
hWinHook = NULL;
|
||||
}
|
||||
if (hShellHook)
|
||||
{
|
||||
UnhookWindowsHookEx(hShellHook);
|
||||
hShellHook = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
|
|
|
@ -8,6 +8,21 @@
|
|||
*/
|
||||
|
||||
#include "kbswitch.h"
|
||||
#include <imm.h>
|
||||
|
||||
/*
|
||||
* This program kbswitch is a mimic of Win2k's internat.exe.
|
||||
* However, there are some differences.
|
||||
*
|
||||
* Comparing with WinNT4 ActivateKeyboardLayout, WinXP ActivateKeyboardLayout has
|
||||
* process boundary, so we cannot activate the IME keyboard layout from the outer process.
|
||||
* It needs special care.
|
||||
*
|
||||
* We use global hook by our kbsdll.dll, to watch the shell and the windows.
|
||||
*
|
||||
* It might not work correctly on Vista+ because keyboard layout change notification
|
||||
* won't be generated in Vista+.
|
||||
*/
|
||||
|
||||
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
||||
|
||||
|
@ -20,6 +35,7 @@ HANDLE hProcessHeap;
|
|||
HMODULE g_hHookDLL = NULL;
|
||||
ULONG ulCurrentLayoutNum = 1;
|
||||
HICON g_hTrayIcon = NULL;
|
||||
HWND g_hwndLastActive = NULL;
|
||||
|
||||
static BOOL
|
||||
GetLayoutID(LPCTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
|
||||
|
@ -65,6 +81,17 @@ GetLayoutID(LPCTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
|
||||
{
|
||||
if (!GetSystemDirectory(szPath, cchPath))
|
||||
return FALSE;
|
||||
|
||||
StringCchCat(szPath, cchPath, TEXT("\\"));
|
||||
StringCchCat(szPath, cchPath, FileName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
|
||||
{
|
||||
|
@ -131,18 +158,86 @@ GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
|
|||
/* Otherwise, use "Layout Text" value as an entry name */
|
||||
dwBufLen = NameLength * sizeof(TCHAR);
|
||||
if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
|
||||
(LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
|
||||
(LPBYTE)szName, &dwBufLen) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szLCID)
|
||||
{
|
||||
HKEY hKey;
|
||||
DWORD dwBufLen;
|
||||
TCHAR szBuf[MAX_PATH];
|
||||
|
||||
szImeFile[0] = UNICODE_NULL;
|
||||
|
||||
if (_tcslen(szLCID) != CCH_LAYOUT_ID)
|
||||
return FALSE; /* Invalid LCID */
|
||||
|
||||
if (szLCID[0] != TEXT('E') && szLCID[0] != TEXT('e'))
|
||||
return FALSE; /* Not an IME HKL */
|
||||
|
||||
StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
|
||||
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID);
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dwBufLen = cchImeFile * sizeof(TCHAR);
|
||||
if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
|
||||
(LPBYTE)szImeFile, &dwBufLen) != ERROR_SUCCESS)
|
||||
{
|
||||
szImeFile[0] = UNICODE_NULL;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return (szImeFile[0] != UNICODE_NULL);
|
||||
}
|
||||
|
||||
typedef struct tagLOAD_ICON
|
||||
{
|
||||
INT cxIcon, cyIcon;
|
||||
HICON hIcon;
|
||||
} LOAD_ICON, *PLOAD_ICON;
|
||||
|
||||
static BOOL CALLBACK
|
||||
EnumResNameProc(
|
||||
HMODULE hModule,
|
||||
LPCTSTR lpszType,
|
||||
LPTSTR lpszName,
|
||||
LPARAM lParam)
|
||||
{
|
||||
PLOAD_ICON pLoadIcon = (PLOAD_ICON)lParam;
|
||||
pLoadIcon->hIcon = (HICON)LoadImage(hModule, lpszName, IMAGE_ICON,
|
||||
pLoadIcon->cxIcon, pLoadIcon->cyIcon,
|
||||
LR_DEFAULTCOLOR);
|
||||
if (pLoadIcon->hIcon)
|
||||
return FALSE; /* Stop enumeration */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
|
||||
{
|
||||
LOAD_ICON LoadIcon = { cxIcon, cyIcon, NULL };
|
||||
HMODULE hImeDLL = LoadLibraryEx(szIconPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
if (hImeDLL)
|
||||
{
|
||||
EnumResourceNames(hImeDLL, RT_GROUP_ICON, EnumResNameProc, (LPARAM)&LoadIcon);
|
||||
FreeLibrary(hImeDLL);
|
||||
}
|
||||
return LoadIcon.hIcon;
|
||||
}
|
||||
|
||||
static HICON
|
||||
CreateTrayIcon(LPTSTR szLCID)
|
||||
CreateTrayIcon(LPTSTR szLCID, LPCTSTR szImeFile OPTIONAL)
|
||||
{
|
||||
LANGID LangID;
|
||||
TCHAR szBuf[4];
|
||||
|
@ -155,6 +250,13 @@ CreateTrayIcon(LPTSTR szLCID)
|
|||
HICON hIcon;
|
||||
INT cxIcon = GetSystemMetrics(SM_CXSMICON);
|
||||
INT cyIcon = GetSystemMetrics(SM_CYSMICON);
|
||||
TCHAR szPath[MAX_PATH];
|
||||
|
||||
if (szImeFile && szImeFile[0])
|
||||
{
|
||||
if (GetSystemLibraryPath(szPath, ARRAYSIZE(szPath), szImeFile))
|
||||
return FakeExtractIcon(szPath, cxIcon, cyIcon);
|
||||
}
|
||||
|
||||
/* Getting "EN", "FR", etc. from English, French, ... */
|
||||
LangID = LANGIDFROMLCID(_tcstoul(szLCID, NULL, 16));
|
||||
|
@ -236,12 +338,14 @@ AddTrayIcon(HWND hwnd)
|
|||
{
|
||||
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
|
||||
TCHAR szLCID[CCH_LAYOUT_ID + 1], szName[MAX_PATH];
|
||||
TCHAR szImeFile[80];
|
||||
|
||||
GetLayoutID(_T("1"), szLCID, ARRAYSIZE(szLCID));
|
||||
GetLayoutName(_T("1"), szName, ARRAYSIZE(szName));
|
||||
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
|
||||
|
||||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||
tnid.hIcon = CreateTrayIcon(szLCID);
|
||||
tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
|
||||
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
||||
|
||||
Shell_NotifyIcon(NIM_ADD, &tnid);
|
||||
|
@ -268,9 +372,12 @@ static VOID
|
|||
UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
|
||||
{
|
||||
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
|
||||
TCHAR szImeFile[80];
|
||||
|
||||
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
|
||||
|
||||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||
tnid.hIcon = CreateTrayIcon(szLCID);
|
||||
tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
|
||||
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
||||
|
||||
Shell_NotifyIcon(NIM_MODIFY, &tnid);
|
||||
|
@ -289,12 +396,12 @@ GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID, SIZE_T LayoutIDLength)
|
|||
static BOOL CALLBACK
|
||||
EnumWindowsProc(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
|
||||
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, lParam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID
|
||||
ActivateLayout(HWND hwnd, ULONG uLayoutNum)
|
||||
ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL)
|
||||
{
|
||||
HKL hKl;
|
||||
TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szLCID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
|
||||
|
@ -311,10 +418,24 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum)
|
|||
/* Switch to the new keyboard layout */
|
||||
GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
|
||||
UpdateTrayIcon(hwnd, szLCID, szLangName);
|
||||
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
||||
|
||||
/* Post WM_INPUTLANGCHANGEREQUEST to every top-level window */
|
||||
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
|
||||
if (hwndTarget)
|
||||
SetForegroundWindow(hwndTarget);
|
||||
|
||||
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
||||
if (hKl)
|
||||
ActivateKeyboardLayout(hKl, KLF_SETFORPROCESS);
|
||||
|
||||
/* Post WM_INPUTLANGCHANGEREQUEST */
|
||||
if (hwndTarget)
|
||||
{
|
||||
PostMessage(hwndTarget, WM_INPUTLANGCHANGEREQUEST,
|
||||
INPUTLANGCHANGE_SYSCHARSET, (LPARAM)hKl);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
|
||||
}
|
||||
|
||||
ulCurrentLayoutNum = uLayoutNum;
|
||||
}
|
||||
|
@ -411,8 +532,16 @@ SetHooks(VOID)
|
|||
VOID
|
||||
DeleteHooks(VOID)
|
||||
{
|
||||
if (KbSwitchDeleteHooks) KbSwitchDeleteHooks();
|
||||
if (g_hHookDLL) FreeLibrary(g_hHookDLL);
|
||||
if (KbSwitchDeleteHooks)
|
||||
{
|
||||
KbSwitchDeleteHooks();
|
||||
KbSwitchDeleteHooks = NULL;
|
||||
}
|
||||
if (g_hHookDLL)
|
||||
{
|
||||
FreeLibrary(g_hHookDLL);
|
||||
g_hHookDLL = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ULONG
|
||||
|
@ -436,7 +565,7 @@ GetNextLayout(VOID)
|
|||
return ulCurrentLayoutNum;
|
||||
}
|
||||
|
||||
LRESULT
|
||||
UINT
|
||||
UpdateLanguageDisplay(HWND hwnd, HKL hKl)
|
||||
{
|
||||
TCHAR szLCID[MAX_PATH], szLangName[MAX_PATH];
|
||||
|
@ -450,12 +579,76 @@ UpdateLanguageDisplay(HWND hwnd, HKL hKl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
LRESULT
|
||||
UpdateLanguageDisplayCurrent(HWND hwnd, WPARAM wParam)
|
||||
HWND
|
||||
GetTargetWindow(HWND hwndFore)
|
||||
{
|
||||
DWORD dwThreadID = GetWindowThreadProcessId((HWND)wParam, 0);
|
||||
TCHAR szClass[64];
|
||||
HWND hwndIME;
|
||||
HWND hwndTarget = hwndFore;
|
||||
if (hwndTarget == NULL)
|
||||
hwndTarget = GetForegroundWindow();
|
||||
|
||||
GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass));
|
||||
if (_tcsicmp(szClass, szKbSwitcherName) == 0)
|
||||
hwndTarget = g_hwndLastActive;
|
||||
|
||||
hwndIME = ImmGetDefaultIMEWnd(hwndTarget);
|
||||
return (hwndIME ? hwndIME : hwndTarget);
|
||||
}
|
||||
|
||||
UINT
|
||||
UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
|
||||
{
|
||||
DWORD dwThreadID = GetWindowThreadProcessId(GetTargetWindow(hwndFore), NULL);
|
||||
HKL hKL = GetKeyboardLayout(dwThreadID);
|
||||
return UpdateLanguageDisplay(hwnd, hKL);
|
||||
UpdateLanguageDisplay(hwnd, hKL);
|
||||
|
||||
if (IsWindow(g_hwndLastActive))
|
||||
SetForegroundWindow(g_hwndLastActive);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT GetCurLayoutNum(HKL hKL)
|
||||
{
|
||||
UINT i, nCount;
|
||||
HKL ahKL[256];
|
||||
|
||||
nCount = GetKeyboardLayoutList(ARRAYSIZE(ahKL), ahKL);
|
||||
for (i = 0; i < nCount; ++i)
|
||||
{
|
||||
if (ahKL[i] == hKL)
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
|
||||
{
|
||||
TCHAR szClass[64];
|
||||
|
||||
hwndFore = GetAncestor(hwndFore, GA_ROOT);
|
||||
|
||||
if (!IsWindowVisible(hwndFore) || !GetClassName(hwndFore, szClass, ARRAYSIZE(szClass)))
|
||||
return FALSE;
|
||||
|
||||
if (_tcsicmp(szClass, szKbSwitcherName) == 0 ||
|
||||
_tcsicmp(szClass, TEXT("Shell_TrayWnd")) == 0)
|
||||
{
|
||||
return FALSE; /* Special window */
|
||||
}
|
||||
|
||||
/* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
|
||||
DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
|
||||
if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
||||
{
|
||||
HKL hKL = GetKeyboardLayout(0);
|
||||
UpdateLanguageDisplay(hwnd, hKL);
|
||||
}
|
||||
|
||||
g_hwndLastActive = hwndFore;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
|
@ -471,31 +664,30 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_CREATE:
|
||||
{
|
||||
if (!SetHooks())
|
||||
{
|
||||
MessageBox(NULL, TEXT("SetHooks failed."), NULL, MB_ICONERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AddTrayIcon(hwnd);
|
||||
|
||||
ActivateLayout(hwnd, ulCurrentLayoutNum);
|
||||
ActivateLayout(hwnd, ulCurrentLayoutNum, NULL);
|
||||
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LANG_CHANGED:
|
||||
case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
|
||||
{
|
||||
return UpdateLanguageDisplay(hwnd, (HKL)lParam);
|
||||
}
|
||||
|
||||
case WM_LOAD_LAYOUT:
|
||||
{
|
||||
ULONG uNextNum = GetNextLayout();
|
||||
if (ulCurrentLayoutNum != uNextNum)
|
||||
ActivateLayout(hwnd, uNextNum);
|
||||
UpdateLanguageDisplay(hwnd, (HKL)lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_WINDOW_ACTIVATE:
|
||||
case WM_WINDOW_ACTIVATE: /* Comes from kbsdll.dll and this module */
|
||||
{
|
||||
return UpdateLanguageDisplayCurrent(hwnd, wParam);
|
||||
HWND hwndFore = GetForegroundWindow();
|
||||
if (RememberLastActive(hwnd, hwndFore))
|
||||
return UpdateLanguageDisplayCurrent(hwnd, hwndFore);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NOTIFYICONMSG:
|
||||
|
@ -537,32 +729,73 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
case ID_EXIT:
|
||||
{
|
||||
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
||||
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_PREFERENCES:
|
||||
{
|
||||
SHELLEXECUTEINFO shInputDll = { sizeof(shInputDll) };
|
||||
shInputDll.hwnd = hwnd;
|
||||
shInputDll.lpVerb = _T("open");
|
||||
shInputDll.lpFile = _T("rundll32.exe");
|
||||
shInputDll.lpParameters = _T("shell32.dll,Control_RunDLL input.dll");
|
||||
if (!ShellExecuteEx(&shInputDll))
|
||||
MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_OK | MB_ICONERROR);
|
||||
|
||||
INT_PTR ret = (INT_PTR)ShellExecute(hwnd, NULL,
|
||||
TEXT("control.exe"), TEXT("input.dll"),
|
||||
NULL, SW_SHOWNORMAL);
|
||||
if (ret <= 32)
|
||||
MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_ICONERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_NEXTLAYOUT:
|
||||
{
|
||||
ActivateLayout(hwnd, GetNextLayout());
|
||||
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 is multithreaded but KLF_SETFORPROCESS and
|
||||
DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
|
||||
if (hwndTarget &&
|
||||
GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) &&
|
||||
_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
||||
{
|
||||
bCONWND = TRUE;
|
||||
hwndTargetSave = hwndTarget;
|
||||
hwndTarget = NULL;
|
||||
}
|
||||
|
||||
if (hwndTarget)
|
||||
{
|
||||
dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||
hKL = GetKeyboardLayout(dwThreadID);
|
||||
uNum = GetCurLayoutNum(hKL);
|
||||
if (uNum != 0)
|
||||
ulCurrentLayoutNum = uNum;
|
||||
}
|
||||
|
||||
ActivateLayout(hwnd, GetNextLayout(), hwndTarget);
|
||||
|
||||
/* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
|
||||
DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
|
||||
if (bCONWND)
|
||||
{
|
||||
ActivateLayout(hwnd, ulCurrentLayoutNum, hwndTargetSave);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
ActivateLayout(hwnd, LOWORD(wParam));
|
||||
if (1 <= LOWORD(wParam) && LOWORD(wParam) <= 1000)
|
||||
{
|
||||
if (!IsWindow(g_hwndLastActive))
|
||||
{
|
||||
g_hwndLastActive = NULL;
|
||||
}
|
||||
ActivateLayout(hwnd, LOWORD(wParam), g_hwndLastActive);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -570,13 +803,10 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case WM_SETTINGCHANGE:
|
||||
{
|
||||
if (wParam == SPI_SETDEFAULTINPUTLANG)
|
||||
{
|
||||
//FIXME: Should detect default language changes by CPL applet or by other tools and update UI
|
||||
}
|
||||
if (wParam == SPI_SETNONCLIENTMETRICS)
|
||||
{
|
||||
return UpdateLanguageDisplayCurrent(hwnd, wParam);
|
||||
PostMessage(hwnd, WM_WINDOW_ACTIVATE, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -597,9 +827,13 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
AddTrayIcon(hwnd);
|
||||
break;
|
||||
}
|
||||
else if (Message == ShellHookMessage && wParam == HSHELL_LANGUAGE)
|
||||
else if (Message == ShellHookMessage)
|
||||
{
|
||||
PostMessage(hwnd, WM_LANG_CHANGED, 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);
|
||||
|
||||
break;
|
||||
}
|
||||
return DefWindowProc(hwnd, Message, wParam, lParam);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#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)
|
||||
|
||||
typedef BOOL (WINAPI *PKBSWITCHSETHOOKS) (VOID);
|
||||
typedef VOID (WINAPI *PKBSWITCHDELETEHOOKS) (VOID);
|
||||
|
|
|
@ -124,11 +124,6 @@ public:
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||||
{
|
||||
return MA_NOACTIVATE;
|
||||
}
|
||||
|
||||
BOOL GetMinimumSize(IN OUT PSIZE pSize)
|
||||
{
|
||||
SIZE szClock = { 0, 0 };
|
||||
|
@ -350,7 +345,6 @@ public:
|
|||
|
||||
BEGIN_MSG_MAP(CTrayNotifyWnd)
|
||||
MESSAGE_HANDLER(WM_CREATE, OnCreate)
|
||||
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
|
||||
MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
|
||||
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
|
||||
MESSAGE_HANDLER(WM_SIZE, OnSize)
|
||||
|
|
|
@ -423,6 +423,9 @@ InputList_Process(VOID)
|
|||
{
|
||||
bRet = InputList_SetFontSubstitutes(pCurrent->pLocale->dwId);
|
||||
InputList_AddInputMethodToUserRegistry(hPreloadKey, hSubstKey, 1, pCurrent);
|
||||
|
||||
/* Activate the DEFAULT entry */
|
||||
ActivateKeyboardLayout(pCurrent->hkl, KLF_RESET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -450,12 +453,12 @@ InputList_Process(VOID)
|
|||
/* Change the default keyboard language */
|
||||
if (SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, 0, &pCurrent->hkl, 0))
|
||||
{
|
||||
DWORD dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS;
|
||||
DWORD dwRecipients = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
|
||||
|
||||
BroadcastSystemMessageW(BSF_POSTMESSAGE,
|
||||
&dwRecipients,
|
||||
WM_INPUTLANGCHANGEREQUEST,
|
||||
0,
|
||||
INPUTLANGCHANGE_SYSCHARSET,
|
||||
(LPARAM)pCurrent->hkl);
|
||||
}
|
||||
|
||||
|
|
|
@ -960,7 +960,7 @@ IntDefWindowProc(
|
|||
if (hwndSwitch)
|
||||
{
|
||||
#define ID_NEXTLAYOUT 10003
|
||||
UserPostMessage(hwndSwitch, WM_COMMAND, ID_NEXTLAYOUT, 0);
|
||||
UserPostMessage(hwndSwitch, WM_COMMAND, ID_NEXTLAYOUT, (LPARAM)UserHMGetHandle(Wnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2356,6 +2356,11 @@ ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
/* Detect Alt+Shift */
|
||||
if (wParam == VK_SHIFT && (msg == WM_SYSKEYDOWN || msg == WM_SYSKEYUP))
|
||||
{
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
OnKey(GuiData, msg, wParam, lParam);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue