mirror of
https://github.com/reactos/reactos.git
synced 2025-04-28 01:11:35 +00:00
[KBSWITCH] Rely on GetKeyboardLayoutList for getting list (#5263)
- Use GetKeyboardLayoutList to get the keyboard list instead of using Preload registry key. - Get the special IDs from registry to handle special HKLs in newly-added LoadSpecialIds function. - Add GetKLIDFromHKL, GetHKLFromLayoutNum, UpdateLayoutList, and GetKLIDFromLayoutNum helper functions. CORE-13145, CORE-10667, CORE-18924
This commit is contained in:
parent
e6bced7a35
commit
a0bef1998e
1 changed files with 225 additions and 189 deletions
|
@ -26,6 +26,13 @@
|
||||||
* won't be generated in Vista+.
|
* won't be generated in Vista+.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define IME_MASK (0xE0000000UL)
|
||||||
|
#define SPECIAL_MASK (0xF0000000UL)
|
||||||
|
|
||||||
|
#define IS_IME_HKL(hKL) ((((ULONG_PTR)(hKL)) & 0xF0000000) == IME_MASK)
|
||||||
|
#define IS_SPECIAL_HKL(hKL) ((((ULONG_PTR)(hKL)) & 0xF0000000) == SPECIAL_MASK)
|
||||||
|
#define SPECIALIDFROMHKL(hKL) ((WORD)(HIWORD(hKL) & 0x0FFF))
|
||||||
|
|
||||||
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
#define WM_NOTIFYICONMSG (WM_USER + 248)
|
||||||
|
|
||||||
PKBSWITCHSETHOOKS KbSwitchSetHooks = NULL;
|
PKBSWITCHSETHOOKS KbSwitchSetHooks = NULL;
|
||||||
|
@ -35,52 +42,158 @@ UINT ShellHookMessage = 0;
|
||||||
HINSTANCE hInst;
|
HINSTANCE hInst;
|
||||||
HANDLE hProcessHeap;
|
HANDLE hProcessHeap;
|
||||||
HMODULE g_hHookDLL = NULL;
|
HMODULE g_hHookDLL = NULL;
|
||||||
ULONG ulCurrentLayoutNum = 1;
|
INT g_nCurrentLayoutNum = 1;
|
||||||
HICON g_hTrayIcon = NULL;
|
HICON g_hTrayIcon = NULL;
|
||||||
HWND g_hwndLastActive = NULL;
|
HWND g_hwndLastActive = NULL;
|
||||||
|
INT g_cKLs = 0;
|
||||||
|
HKL g_ahKLs[64];
|
||||||
|
|
||||||
static BOOL
|
typedef struct
|
||||||
GetLayoutID(LPCTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
|
|
||||||
{
|
{
|
||||||
DWORD dwBufLen, dwRes;
|
DWORD dwLayoutId;
|
||||||
HKEY hKey;
|
HKL hKL;
|
||||||
TCHAR szTempLCID[CCH_LAYOUT_ID + 1];
|
TCHAR szKLID[CCH_LAYOUT_ID + 1];
|
||||||
|
} SPECIAL_ID, *PSPECIAL_ID;
|
||||||
|
|
||||||
/* Get the Layout ID */
|
SPECIAL_ID g_SpecialIds[80];
|
||||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE,
|
INT g_cSpecialIds = 0;
|
||||||
&hKey) == ERROR_SUCCESS)
|
|
||||||
|
static VOID LoadSpecialIds(VOID)
|
||||||
|
{
|
||||||
|
TCHAR szKLID[KL_NAMELENGTH], szLayoutId[16];
|
||||||
|
DWORD dwSize, dwIndex;
|
||||||
|
HKEY hKey, hLayoutKey;
|
||||||
|
|
||||||
|
g_cSpecialIds = 0;
|
||||||
|
|
||||||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||||
|
TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"),
|
||||||
|
0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
dwBufLen = sizeof(szTempLCID);
|
return;
|
||||||
dwRes = RegQueryValueEx(hKey, szLayoutNum, NULL, NULL, (LPBYTE)szTempLCID, &dwBufLen);
|
|
||||||
if (dwRes != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for a substitute of this layout */
|
for (dwIndex = 0; dwIndex < 1000; ++dwIndex)
|
||||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"), 0,
|
|
||||||
KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
dwBufLen = sizeof(szTempLCID);
|
dwSize = ARRAYSIZE(szKLID);
|
||||||
if (RegQueryValueEx(hKey, szTempLCID, NULL, NULL, (LPBYTE)szLCID, &dwBufLen) != ERROR_SUCCESS)
|
if (RegEnumKeyEx(hKey, dwIndex, szKLID, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (RegOpenKeyEx(hKey, szKLID, 0, KEY_READ, &hLayoutKey) != ERROR_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dwSize = sizeof(szLayoutId);
|
||||||
|
if (RegQueryValueEx(hLayoutKey, TEXT("Layout Id"), NULL, NULL,
|
||||||
|
(LPBYTE)szLayoutId, &dwSize) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
/* No substitute found, then use the old LCID */
|
DWORD dwKLID = _tcstoul(szKLID, NULL, 16);
|
||||||
StringCchCopy(szLCID, LCIDLength, szTempLCID);
|
WORD wLangId = LOWORD(dwKLID), wLayoutId = LOWORD(_tcstoul(szLayoutId, NULL, 16));
|
||||||
|
HKL hKL = (HKL)(LONG_PTR)(SPECIAL_MASK | MAKELONG(wLangId, wLayoutId));
|
||||||
|
|
||||||
|
/* Add a special ID */
|
||||||
|
g_SpecialIds[g_cSpecialIds].dwLayoutId = wLayoutId;
|
||||||
|
g_SpecialIds[g_cSpecialIds].hKL = hKL;
|
||||||
|
StringCchCopy(g_SpecialIds[g_cSpecialIds].szKLID,
|
||||||
|
ARRAYSIZE(g_SpecialIds[g_cSpecialIds].szKLID), szKLID);
|
||||||
|
++g_cSpecialIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hLayoutKey);
|
||||||
|
|
||||||
|
if (g_cSpecialIds >= ARRAYSIZE(g_SpecialIds))
|
||||||
|
{
|
||||||
|
OutputDebugStringA("g_SpecialIds is full!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
|
||||||
|
{
|
||||||
|
szKLID[0] = 0;
|
||||||
|
|
||||||
|
if (IS_IME_HKL(hKL))
|
||||||
|
{
|
||||||
|
StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), (DWORD)(DWORD_PTR)hKL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_SPECIAL_HKL(hKL))
|
||||||
|
{
|
||||||
|
INT i;
|
||||||
|
for (i = 0; i < g_cSpecialIds; ++i)
|
||||||
|
{
|
||||||
|
if (g_SpecialIds[i].hKL == hKL)
|
||||||
|
{
|
||||||
|
StringCchCopy(szKLID, KLIDLength, g_SpecialIds[i].szKLID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Substitutes key couldn't be opened, so use the old LCID */
|
StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), LOWORD(hKL));
|
||||||
StringCchCopy(szLCID, LCIDLength, szTempLCID);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID UpdateLayoutList(HKL hKL OPTIONAL)
|
||||||
|
{
|
||||||
|
INT iKL;
|
||||||
|
|
||||||
|
if (!hKL)
|
||||||
|
{
|
||||||
|
if (0 <= (g_nCurrentLayoutNum - 1) && (g_nCurrentLayoutNum - 1) < g_cKLs)
|
||||||
|
{
|
||||||
|
hKL = g_ahKLs[g_nCurrentLayoutNum - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HWND hwndTarget = (g_hwndLastActive ? g_hwndLastActive : GetForegroundWindow());
|
||||||
|
DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||||
|
hKL = GetKeyboardLayout(dwTID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
g_cKLs = GetKeyboardLayoutList(ARRAYSIZE(g_ahKLs), g_ahKLs);
|
||||||
|
|
||||||
|
g_nCurrentLayoutNum = -1;
|
||||||
|
for (iKL = 0; iKL < g_cKLs; ++iKL)
|
||||||
|
{
|
||||||
|
if (g_ahKLs[iKL] == hKL)
|
||||||
|
{
|
||||||
|
g_nCurrentLayoutNum = iKL + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_nCurrentLayoutNum == -1 && g_cKLs < ARRAYSIZE(g_ahKLs))
|
||||||
|
{
|
||||||
|
g_nCurrentLayoutNum = g_cKLs;
|
||||||
|
g_ahKLs[g_cKLs++] = hKL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
|
||||||
|
{
|
||||||
|
GetKLIDFromHKL(GetHKLFromLayoutNum(nLayoutNum), szKLID, KLIDLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
|
@ -95,21 +208,19 @@ GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
|
GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD dwBufLen;
|
DWORD dwBufLen;
|
||||||
TCHAR szBuf[MAX_PATH];
|
TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1];
|
||||||
TCHAR szLCID[CCH_LAYOUT_ID + 1];
|
|
||||||
|
|
||||||
if (!GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID)))
|
GetKLIDFromLayoutNum(nLayoutNum, szKLID, ARRAYSIZE(szKLID));
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
|
StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
|
||||||
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID);
|
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
|
||||||
|
|
||||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Use "Layout Display Name" value as an entry name if possible */
|
/* Use "Layout Display Name" value as an entry name if possible */
|
||||||
|
@ -123,17 +234,17 @@ GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
|
||||||
/* Otherwise, use "Layout Text" value as an entry name */
|
/* Otherwise, use "Layout Text" value as an entry name */
|
||||||
dwBufLen = NameLength * sizeof(TCHAR);
|
dwBufLen = NameLength * sizeof(TCHAR);
|
||||||
if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
|
if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
|
||||||
(LPBYTE)szName, &dwBufLen) != ERROR_SUCCESS)
|
(LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
return FALSE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
return TRUE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szLCID)
|
static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
DWORD dwBufLen;
|
DWORD dwBufLen;
|
||||||
|
@ -141,19 +252,17 @@ static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szLCID)
|
||||||
|
|
||||||
szImeFile[0] = UNICODE_NULL;
|
szImeFile[0] = UNICODE_NULL;
|
||||||
|
|
||||||
if (_tcslen(szLCID) != CCH_LAYOUT_ID)
|
if (_tcslen(szKLID) != CCH_LAYOUT_ID)
|
||||||
return FALSE; /* Invalid LCID */
|
return FALSE; /* Invalid LCID */
|
||||||
|
|
||||||
if (szLCID[0] != TEXT('E') && szLCID[0] != TEXT('e'))
|
if (szKLID[0] != TEXT('E') && szKLID[0] != TEXT('e'))
|
||||||
return FALSE; /* Not an IME HKL */
|
return FALSE; /* Not an IME HKL */
|
||||||
|
|
||||||
StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
|
StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
|
||||||
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID);
|
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
|
||||||
|
|
||||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
dwBufLen = cchImeFile * sizeof(TCHAR);
|
dwBufLen = cchImeFile * sizeof(TCHAR);
|
||||||
if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
|
if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
|
||||||
|
@ -223,7 +332,7 @@ static HBITMAP BitmapFromIcon(HICON hIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
static HICON
|
static HICON
|
||||||
CreateTrayIcon(LPTSTR szLCID, LPCTSTR szImeFile OPTIONAL)
|
CreateTrayIcon(LPTSTR szKLID, LPCTSTR szImeFile OPTIONAL)
|
||||||
{
|
{
|
||||||
LANGID LangID;
|
LANGID LangID;
|
||||||
TCHAR szBuf[4];
|
TCHAR szBuf[4];
|
||||||
|
@ -245,7 +354,7 @@ CreateTrayIcon(LPTSTR szLCID, LPCTSTR szImeFile OPTIONAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getting "EN", "FR", etc. from English, French, ... */
|
/* Getting "EN", "FR", etc. from English, French, ... */
|
||||||
LangID = LANGIDFROMLCID(_tcstoul(szLCID, NULL, 16));
|
LangID = LANGIDFROMLCID(_tcstoul(szKLID, NULL, 16));
|
||||||
if (GetLocaleInfo(LangID,
|
if (GetLocaleInfo(LangID,
|
||||||
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
|
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
|
||||||
szBuf,
|
szBuf,
|
||||||
|
@ -323,15 +432,14 @@ static VOID
|
||||||
AddTrayIcon(HWND hwnd)
|
AddTrayIcon(HWND hwnd)
|
||||||
{
|
{
|
||||||
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
|
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
|
||||||
TCHAR szLCID[CCH_LAYOUT_ID + 1], szName[MAX_PATH];
|
TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80];
|
||||||
TCHAR szImeFile[80];
|
|
||||||
|
|
||||||
GetLayoutID(_T("1"), szLCID, ARRAYSIZE(szLCID));
|
GetKLIDFromLayoutNum(g_nCurrentLayoutNum, szKLID, ARRAYSIZE(szKLID));
|
||||||
GetLayoutName(_T("1"), szName, ARRAYSIZE(szName));
|
GetLayoutName(g_nCurrentLayoutNum, szName, ARRAYSIZE(szName));
|
||||||
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
|
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
|
||||||
|
|
||||||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||||
tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
|
tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
|
||||||
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
||||||
|
|
||||||
Shell_NotifyIcon(NIM_ADD, &tnid);
|
Shell_NotifyIcon(NIM_ADD, &tnid);
|
||||||
|
@ -355,15 +463,15 @@ DeleteTrayIcon(HWND hwnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
|
UpdateTrayIcon(HWND hwnd, LPTSTR szKLID, LPTSTR szName)
|
||||||
{
|
{
|
||||||
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
|
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
|
||||||
TCHAR szImeFile[80];
|
TCHAR szImeFile[80];
|
||||||
|
|
||||||
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
|
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
|
||||||
|
|
||||||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||||
tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
|
tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
|
||||||
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
|
||||||
|
|
||||||
Shell_NotifyIcon(NIM_MODIFY, &tnid);
|
Shell_NotifyIcon(NIM_MODIFY, &tnid);
|
||||||
|
@ -373,12 +481,6 @@ UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
|
||||||
g_hTrayIcon = tnid.hIcon;
|
g_hTrayIcon = tnid.hIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
|
||||||
GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID, SIZE_T LayoutIDLength)
|
|
||||||
{
|
|
||||||
StringCchPrintf(szLayoutID, LayoutIDLength, _T("%08lx"), (DWORD)(DWORD_PTR)(hKl));
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK
|
static BOOL CALLBACK
|
||||||
EnumWindowsProc(HWND hwnd, LPARAM lParam)
|
EnumWindowsProc(HWND hwnd, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
@ -390,25 +492,24 @@ static VOID
|
||||||
ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
|
ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
|
||||||
{
|
{
|
||||||
HKL hKl;
|
HKL hKl;
|
||||||
TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szLCID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
|
TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
|
||||||
LANGID LangID;
|
LANGID LangID;
|
||||||
|
|
||||||
/* The layout number starts from one. Zero is invalid */
|
/* The layout number starts from one. Zero is invalid */
|
||||||
if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
|
if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_ultot(uLayoutNum, szLayoutNum, 10);
|
GetKLIDFromLayoutNum(uLayoutNum, szKLID, ARRAYSIZE(szKLID));
|
||||||
GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID));
|
LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
|
||||||
LangID = (LANGID)_tcstoul(szLCID, NULL, 16);
|
|
||||||
|
|
||||||
/* Switch to the new keyboard layout */
|
/* Switch to the new keyboard layout */
|
||||||
GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
|
GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
|
||||||
UpdateTrayIcon(hwnd, szLCID, szLangName);
|
UpdateTrayIcon(hwnd, szKLID, szLangName);
|
||||||
|
|
||||||
if (hwndTarget && !bNoActivate)
|
if (hwndTarget && !bNoActivate)
|
||||||
SetForegroundWindow(hwndTarget);
|
SetForegroundWindow(hwndTarget);
|
||||||
|
|
||||||
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
hKl = LoadKeyboardLayout(szKLID, KLF_ACTIVATE);
|
||||||
if (hKl)
|
if (hKl)
|
||||||
ActivateKeyboardLayout(hKl, KLF_SETFORPROCESS);
|
ActivateKeyboardLayout(hKl, KLF_SETFORPROCESS);
|
||||||
|
|
||||||
|
@ -423,97 +524,47 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoAc
|
||||||
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
|
EnumWindows(EnumWindowsProc, (LPARAM) hKl);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulCurrentLayoutNum = uLayoutNum;
|
g_nCurrentLayoutNum = uLayoutNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HMENU
|
static HMENU
|
||||||
BuildLeftPopupMenu(VOID)
|
BuildLeftPopupMenu(VOID)
|
||||||
{
|
{
|
||||||
HMENU hMenu = CreatePopupMenu();
|
HMENU hMenu = CreatePopupMenu();
|
||||||
HKEY hKey;
|
TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80];
|
||||||
DWORD dwIndex, dwSize;
|
|
||||||
TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szName[MAX_PATH];
|
|
||||||
TCHAR szLCID[CCH_LAYOUT_ID + 1], szImeFile[80];
|
|
||||||
HICON hIcon;
|
HICON hIcon;
|
||||||
MENUITEMINFO mii = { sizeof(mii) };
|
MENUITEMINFO mii = { sizeof(mii) };
|
||||||
|
INT iKL;
|
||||||
|
|
||||||
/* Add the keyboard layouts to the popup menu */
|
for (iKL = 0; iKL < g_cKLs; ++iKL)
|
||||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0,
|
|
||||||
KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
for (dwIndex = 0; ; dwIndex++)
|
GetKLIDFromHKL(g_ahKLs[iKL], szKLID, ARRAYSIZE(szKLID));
|
||||||
|
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
|
||||||
|
|
||||||
|
if (!GetLayoutName(iKL + 1, szName, ARRAYSIZE(szName)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mii.fMask = MIIM_ID | MIIM_STRING;
|
||||||
|
mii.wID = iKL + 1;
|
||||||
|
mii.dwTypeData = szName;
|
||||||
|
|
||||||
|
hIcon = CreateTrayIcon(szKLID, szImeFile);
|
||||||
|
if (hIcon)
|
||||||
{
|
{
|
||||||
dwSize = sizeof(szLayoutNum);
|
mii.hbmpItem = BitmapFromIcon(hIcon);
|
||||||
if (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL,
|
if (mii.hbmpItem)
|
||||||
NULL, NULL) != ERROR_SUCCESS)
|
mii.fMask |= MIIM_BITMAP;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID));
|
|
||||||
GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
|
|
||||||
|
|
||||||
if (!GetLayoutName(szLayoutNum, szName, ARRAYSIZE(szName)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mii.fMask = MIIM_ID | MIIM_STRING;
|
|
||||||
mii.wID = _ttoi(szLayoutNum);
|
|
||||||
mii.dwTypeData = szName;
|
|
||||||
|
|
||||||
hIcon = CreateTrayIcon(szLCID, szImeFile);
|
|
||||||
if (hIcon)
|
|
||||||
{
|
|
||||||
mii.hbmpItem = BitmapFromIcon(hIcon);
|
|
||||||
if (mii.hbmpItem)
|
|
||||||
mii.fMask |= MIIM_BITMAP;
|
|
||||||
}
|
|
||||||
|
|
||||||
InsertMenuItem(hMenu, -1, TRUE, &mii);
|
|
||||||
DestroyIcon(hIcon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckMenuItem(hMenu, ulCurrentLayoutNum, MF_CHECKED);
|
InsertMenuItem(hMenu, -1, TRUE, &mii);
|
||||||
|
DestroyIcon(hIcon);
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckMenuItem(hMenu, g_nCurrentLayoutNum, MF_CHECKED);
|
||||||
|
|
||||||
return hMenu;
|
return hMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG
|
|
||||||
GetMaxLayoutNum(VOID)
|
|
||||||
{
|
|
||||||
HKEY hKey;
|
|
||||||
ULONG dwIndex, dwSize, uLayoutNum, uMaxLayoutNum = 0;
|
|
||||||
TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szLayoutID[CCH_LAYOUT_ID + 1];
|
|
||||||
|
|
||||||
/* Get the maximum layout number in the Preload key */
|
|
||||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0,
|
|
||||||
KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
for (dwIndex = 0; ; dwIndex++)
|
|
||||||
{
|
|
||||||
dwSize = sizeof(szLayoutNum);
|
|
||||||
if (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL,
|
|
||||||
NULL, NULL) != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
|
|
||||||
{
|
|
||||||
uLayoutNum = _ttoi(szLayoutNum);
|
|
||||||
if (uMaxLayoutNum < uLayoutNum)
|
|
||||||
uMaxLayoutNum = uLayoutNum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uMaxLayoutNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
SetHooks(VOID)
|
SetHooks(VOID)
|
||||||
{
|
{
|
||||||
|
@ -549,37 +600,36 @@ DeleteHooks(VOID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT GetLayoutNum(HKL hKL)
|
||||||
|
{
|
||||||
|
INT iKL;
|
||||||
|
|
||||||
|
for (iKL = 0; iKL < g_cKLs; ++iKL)
|
||||||
|
{
|
||||||
|
if (g_ahKLs[iKL] == hKL)
|
||||||
|
return iKL + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
GetNextLayout(VOID)
|
GetNextLayout(VOID)
|
||||||
{
|
{
|
||||||
TCHAR szLayoutNum[3 + 1], szLayoutID[CCH_LAYOUT_ID + 1];
|
return (g_nCurrentLayoutNum % g_cKLs) + 1;
|
||||||
ULONG uLayoutNum, uMaxNum = GetMaxLayoutNum();
|
|
||||||
|
|
||||||
for (uLayoutNum = ulCurrentLayoutNum + 1; ; ++uLayoutNum)
|
|
||||||
{
|
|
||||||
if (uLayoutNum > uMaxNum)
|
|
||||||
uLayoutNum = 1;
|
|
||||||
if (uLayoutNum == ulCurrentLayoutNum)
|
|
||||||
break;
|
|
||||||
|
|
||||||
_ultot(uLayoutNum, szLayoutNum, 10);
|
|
||||||
if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
|
|
||||||
return uLayoutNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ulCurrentLayoutNum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT
|
UINT
|
||||||
UpdateLanguageDisplay(HWND hwnd, HKL hKl)
|
UpdateLanguageDisplay(HWND hwnd, HKL hKL)
|
||||||
{
|
{
|
||||||
TCHAR szLCID[MAX_PATH], szLangName[MAX_PATH];
|
TCHAR szKLID[MAX_PATH], szLangName[MAX_PATH];
|
||||||
LANGID LangID;
|
LANGID LangID;
|
||||||
|
|
||||||
GetLayoutIDByHkl(hKl, szLCID, ARRAYSIZE(szLCID));
|
GetKLIDFromHKL(hKL, szKLID, ARRAYSIZE(szKLID));
|
||||||
LangID = (LANGID)_tcstoul(szLCID, NULL, 16);
|
LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
|
||||||
GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
|
GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
|
||||||
UpdateTrayIcon(hwnd, szLCID, szLangName);
|
UpdateTrayIcon(hwnd, szKLID, szLangName);
|
||||||
|
g_nCurrentLayoutNum = GetLayoutNum(hKL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -611,21 +661,6 @@ UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
|
||||||
return 0;
|
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)
|
static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
|
||||||
{
|
{
|
||||||
TCHAR szClass[64];
|
TCHAR szClass[64];
|
||||||
|
@ -641,8 +676,7 @@ static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
|
||||||
return FALSE; /* Special window */
|
return FALSE; /* Special window */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
|
/* FIXME: CONWND needs special handling */
|
||||||
DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
|
|
||||||
if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
||||||
{
|
{
|
||||||
HKL hKL = GetKeyboardLayout(0);
|
HKL hKL = GetKeyboardLayout(0);
|
||||||
|
@ -671,15 +705,19 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadSpecialIds();
|
||||||
|
|
||||||
|
UpdateLayoutList(NULL);
|
||||||
AddTrayIcon(hwnd);
|
AddTrayIcon(hwnd);
|
||||||
|
|
||||||
ActivateLayout(hwnd, ulCurrentLayoutNum, NULL, TRUE);
|
ActivateLayout(hwnd, g_nCurrentLayoutNum, NULL, TRUE);
|
||||||
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
|
case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
|
||||||
{
|
{
|
||||||
|
UpdateLayoutList((HKL)lParam);
|
||||||
UpdateLanguageDisplay(hwnd, (HKL)lParam);
|
UpdateLanguageDisplay(hwnd, (HKL)lParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -757,8 +795,7 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
if (hwndTarget == NULL)
|
if (hwndTarget == NULL)
|
||||||
hwndTarget = g_hwndLastActive;
|
hwndTarget = g_hwndLastActive;
|
||||||
|
|
||||||
/* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
|
/* FIXME: CONWND needs special handling */
|
||||||
DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
|
|
||||||
if (hwndTarget &&
|
if (hwndTarget &&
|
||||||
GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) &&
|
GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) &&
|
||||||
_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
|
||||||
|
@ -772,19 +809,17 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
|
dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
|
||||||
hKL = GetKeyboardLayout(dwThreadID);
|
hKL = GetKeyboardLayout(dwThreadID);
|
||||||
uNum = GetCurLayoutNum(hKL);
|
uNum = GetLayoutNum(hKL);
|
||||||
if (uNum != 0)
|
if (uNum != 0)
|
||||||
ulCurrentLayoutNum = uNum;
|
g_nCurrentLayoutNum = uNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
|
ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
|
||||||
|
|
||||||
/* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
|
/* FIXME: CONWND needs special handling */
|
||||||
DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
|
|
||||||
if (bCONWND)
|
if (bCONWND)
|
||||||
{
|
ActivateLayout(hwnd, g_nCurrentLayoutNum, hwndTargetSave, TRUE);
|
||||||
ActivateLayout(hwnd, ulCurrentLayoutNum, hwndTargetSave, TRUE);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,6 +861,7 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (Message == s_uTaskbarRestart)
|
if (Message == s_uTaskbarRestart)
|
||||||
{
|
{
|
||||||
|
UpdateLayoutList(NULL);
|
||||||
AddTrayIcon(hwnd);
|
AddTrayIcon(hwnd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue