diff --git a/reactos/base/applications/kbswitch/kbswitch.c b/reactos/base/applications/kbswitch/kbswitch.c index 6f7630481bc..ab2af7b5975 100644 --- a/reactos/base/applications/kbswitch/kbswitch.c +++ b/reactos/base/applications/kbswitch/kbswitch.c @@ -1,4 +1,12 @@ -#include +/* + * 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) + */ + +#include "kbswitch.h" #define WM_NOTIFYICONMSG (WM_USER + 248) #define BUFSIZE 256 @@ -9,13 +17,13 @@ HWND hwnd; static VOID AddTrayIcon(HWND hwnd, HICON hIcon) { - NOTIFYICONDATA tnid; + NOTIFYICONDATA tnid; tnid.cbSize = sizeof(NOTIFYICONDATA); tnid.hWnd = hwnd; tnid.uID = 1; tnid.uFlags = NIF_ICON | NIF_MESSAGE; - tnid.uCallbackMessage = WM_NOTIFYICONMSG; + tnid.uCallbackMessage = WM_NOTIFYICONMSG; tnid.hIcon = hIcon; Shell_NotifyIcon(NIM_ADD, &tnid); @@ -26,156 +34,199 @@ AddTrayIcon(HWND hwnd, HICON hIcon) static VOID DelTrayIcon(HWND hwnd) { - NOTIFYICONDATA tnid; + NOTIFYICONDATA tnid; - tnid.cbSize = sizeof(NOTIFYICONDATA); - tnid.hWnd = hwnd; - tnid.uID = 1; + tnid.cbSize = sizeof(NOTIFYICONDATA); + tnid.hWnd = hwnd; + tnid.uID = 1; - Shell_NotifyIcon(NIM_DELETE, &tnid); + Shell_NotifyIcon(NIM_DELETE, &tnid); } static BOOL -GetLayoutName(LPCTSTR lcid, LPTSTR name) +GetLayoutID(LPTSTR szLayoutNum, LPTSTR szLCID) +{ + DWORD dwBufLen; + DWORD dwTest; + HKEY hKey; + TCHAR szTempLCID[CCH_LAYOUT_ID + 1]; + + // Get the Layout ID + if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + dwBufLen = sizeof(szTempLCID); + + if(RegQueryValueEx(hKey, szLayoutNum, NULL, NULL, (LPBYTE)szTempLCID, &dwBufLen) != ERROR_SUCCESS) + { + RegCloseKey(hKey); + return FALSE; + } + + RegCloseKey(hKey); + } + + // Look for a substitude of this layout + if(RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + dwBufLen = sizeof(szTempLCID); + + if(RegQueryValueEx(hKey, szTempLCID, NULL, NULL, (LPBYTE)szLCID, &dwBufLen) != ERROR_SUCCESS) + { + // No substitute found, then use the old LCID + lstrcpy(szLCID, szTempLCID); + } + + RegCloseKey(hKey); + } + else + { + // Substitutes key couldn't be opened, so use the old LCID + lstrcpy(szLCID, szTempLCID); + } + + return TRUE; +} + +static BOOL +GetLayoutName(LPTSTR szLayoutNum, LPTSTR szName) { HKEY hKey; DWORD dwBufLen; - TCHAR szBuf[BUFSIZE]; + TCHAR szBuf[MAX_PATH]; + TCHAR szLCID[CCH_LAYOUT_ID + 1]; - _stprintf(szBuf, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"),lcid); + if(!GetLayoutID(szLayoutNum, szLCID)) + return FALSE; + + wsprintf(szBuf, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szLCID); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)szBuf, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { - dwBufLen = BUFSIZE; - if (RegQueryValueEx(hKey,_T("Layout Text"),NULL,NULL,(LPBYTE)name,&dwBufLen) == ERROR_SUCCESS) + dwBufLen = MAX_PATH * sizeof(TCHAR); + + if(RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL, (LPBYTE)szName, &dwBufLen) != ERROR_SUCCESS) { RegCloseKey(hKey); - return TRUE; + return FALSE; } + + RegCloseKey(hKey); } - return FALSE; + return TRUE; } static VOID -ActivateLayout(INT LayoutID) +ActivateLayout(ULONG uLayoutNum) { - TCHAR szLayoutID[MAX_PATH], szNewLayout[MAX_PATH]; - HKEY hKey; - DWORD dwBufLen; + HKL hKl; + TCHAR szLayoutNum[CCH_ULONG_DEC + 1]; + TCHAR szLCID[CCH_LAYOUT_ID + 1]; + DWORD Ret; - _stprintf(szLayoutID, _T("%d"), LayoutID); + _ultot(uLayoutNum, szLayoutNum, 10); + GetLayoutID(szLayoutNum, szLCID); - if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) - { - dwBufLen = MAX_PATH; - if (RegQueryValueEx(hKey, szLayoutID, NULL, NULL, (LPBYTE)szNewLayout, &dwBufLen) == ERROR_SUCCESS) - { - MessageBox(0, szNewLayout, _T(""), MB_OK); - RegCloseKey(hKey); - } - } + // Switch to the new keyboard layout + hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE); + Ret = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDWININICHANGE); } -static VOID -ShowPopupMenu(HWND hwnd, POINT pt) +static HMENU +BuildPopupMenu() { - HMENU hMenu; - HKEY hKey; - DWORD dwIndex = 0, dwSize, dwType; - LONG Ret; - TCHAR szBuf[MAX_PATH], szPreload[MAX_PATH], szName[MAX_PATH]; + HMENU hMenu; + HKEY hKey; + DWORD dwIndex, dwSize; + TCHAR szLayoutNum[CCH_ULONG_DEC + 1]; + TCHAR szName[MAX_PATH]; - hMenu = CreatePopupMenu(); + hMenu = CreatePopupMenu(); - if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), - 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) - { - dwSize = MAX_PATH; - Ret = RegEnumValue(hKey, dwIndex, szBuf, &dwSize, NULL, &dwType, NULL, NULL); - if (Ret == ERROR_SUCCESS) - { - while (Ret == ERROR_SUCCESS) - { - dwSize = MAX_PATH; - RegQueryValueEx(hKey, szBuf, NULL, NULL, (LPBYTE)szPreload, &dwSize); + 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; - GetLayoutName(szPreload, szName); - AppendMenu(hMenu, MF_STRING, _ttoi(szBuf), szName); + if(!GetLayoutName(szLayoutNum, szName)) + break; - dwIndex++; + AppendMenu(hMenu, MF_STRING, _ttoi(szLayoutNum), szName); + } - dwSize = MAX_PATH; - Ret = RegEnumValue(hKey, dwIndex, szBuf, &dwSize, NULL, &dwType, NULL, NULL); - } - } - } + RegCloseKey(hKey); + } - TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwnd, NULL); - DestroyMenu(hMenu); - RegCloseKey(hKey); + return hMenu; } LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { - POINT pt; + static HMENU hPopupMenu; - switch (Message) - { - case WM_CREATE: - AddTrayIcon(hwnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN))); - break; + switch (Message) + { + case WM_CREATE: + AddTrayIcon(hwnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN))); + hPopupMenu = BuildPopupMenu(hwnd); + break; - case WM_NOTIFYICONMSG: - switch (lParam) - { - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - { - GetCursorPos(&pt); - ShowPopupMenu(hwnd, pt); - } - break; - } - break; + case WM_NOTIFYICONMSG: + switch (lParam) + { + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + { + POINT pt; - case WM_COMMAND: - ActivateLayout(LOWORD(wParam)); - break; + GetCursorPos(&pt); + TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL); + } + break; + } + break; - case WM_DESTROY: - DelTrayIcon(hwnd); - PostQuitMessage(0); - break; - } + case WM_COMMAND: + ActivateLayout(LOWORD(wParam)); + break; - return DefWindowProc(hwnd, Message, wParam, lParam); + case WM_DESTROY: + DestroyMenu(hPopupMenu); + DelTrayIcon(hwnd); + PostQuitMessage(0); + break; + } + + return DefWindowProc(hwnd, Message, wParam, lParam); } INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow) { - WNDCLASS WndClass = {0}; - MSG msg; + WNDCLASS WndClass = {0}; + MSG msg; - hInst = hInstance; + hInst = hInstance; - WndClass.style = 0; - WndClass.lpfnWndProc = (WNDPROC)WndProc; - WndClass.cbClsExtra = 0; - WndClass.cbWndExtra = 0; - WndClass.hInstance = hInstance; - WndClass.hIcon = NULL; - WndClass.hCursor = NULL; - WndClass.hbrBackground = NULL; - WndClass.lpszMenuName = NULL; - WndClass.lpszClassName = L"kbswitch"; + WndClass.style = 0; + WndClass.lpfnWndProc = (WNDPROC)WndProc; + WndClass.cbClsExtra = 0; + WndClass.cbWndExtra = 0; + WndClass.hInstance = hInstance; + WndClass.hIcon = NULL; + WndClass.hCursor = NULL; + WndClass.hbrBackground = NULL; + WndClass.lpszMenuName = NULL; + WndClass.lpszClassName = L"kbswitch"; - if (!RegisterClass(&WndClass)) return 0; + if (!RegisterClass(&WndClass)) return 0; - hwnd = CreateWindow(L"kbswitch", L"kbswitch", 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, hInstance, NULL); + hwnd = CreateWindow(L"kbswitch", L"kbswitch", 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, hInstance, NULL); while(GetMessage(&msg,NULL,0,0)) { diff --git a/reactos/base/applications/kbswitch/kbswitch.h b/reactos/base/applications/kbswitch/kbswitch.h index f281629b1b8..1be3801cef6 100644 --- a/reactos/base/applications/kbswitch/kbswitch.h +++ b/reactos/base/applications/kbswitch/kbswitch.h @@ -1,6 +1,11 @@ +#include #include #include -#include -#include #include "resource.h" + +// Character Count of a layout ID like "00000409" +#define CCH_LAYOUT_ID 8 + +// Maximum Character Count of a ULONG in decimal +#define CCH_ULONG_DEC 10