Author: cfinck Date: Sun Apr 20 10:48:43 2008 New Revision: 33062
URL: http://svn.reactos.org/svn/reactos?rev=33062&view=rev Log: - Add the actual function for switching the keyboard layout - Handle keyboard layout substitutes (like the "German (IBM)" layout) - Refactor many parts of the code: * Always close hKey handles after they were successfully opened * Build the keyboard layout menu one time and not everytime, when it's opened * Use smaller sizes for some string variables, defined with CCH_LAYOUT_ID and CCH_ULONG_DEC. This also ensures that we don't retrieve bigger values, which would be invalid. - Use a consistent indentation
Modified: trunk/reactos/base/applications/kbswitch/kbswitch.c trunk/reactos/base/applications/kbswitch/kbswitch.h
Modified: trunk/reactos/base/applications/kbswitch/kbswitch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/kbswitch/... ============================================================================== --- trunk/reactos/base/applications/kbswitch/kbswitch.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/kbswitch/kbswitch.c [iso-8859-1] Sun Apr 20 10:48:43 2008 @@ -1,4 +1,12 @@ -#include <kbswitch.h> +/* + * 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 @@ 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 @@ static VOID DelTrayIcon(HWND hwnd) { - NOTIFYICONDATA tnid; - - tnid.cbSize = sizeof(NOTIFYICONDATA); - tnid.hWnd = hwnd; - tnid.uID = 1; - - Shell_NotifyIcon(NIM_DELETE, &tnid); + NOTIFYICONDATA tnid; + + tnid.cbSize = sizeof(NOTIFYICONDATA); + tnid.hWnd = hwnd; + tnid.uID = 1; + + 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]; - - _stprintf(szBuf, _T("SYSTEM\CurrentControlSet\Control\Keyboard Layouts\%s"),lcid); + TCHAR szBuf[MAX_PATH]; + TCHAR szLCID[CCH_LAYOUT_ID + 1]; + + 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; + return FALSE; + } + + RegCloseKey(hKey); + } + + return TRUE; }
static VOID -ActivateLayout(INT LayoutID) -{ - TCHAR szLayoutID[MAX_PATH], szNewLayout[MAX_PATH]; - HKEY hKey; - DWORD dwBufLen; - - _stprintf(szLayoutID, _T("%d"), LayoutID); - - 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); - } - } -} - -static VOID -ShowPopupMenu(HWND hwnd, POINT pt) -{ - HMENU hMenu; - HKEY hKey; - DWORD dwIndex = 0, dwSize, dwType; - LONG Ret; - TCHAR szBuf[MAX_PATH], szPreload[MAX_PATH], szName[MAX_PATH]; - - 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); - - GetLayoutName(szPreload, szName); - AppendMenu(hMenu, MF_STRING, _ttoi(szBuf), szName); - - dwIndex++; - - dwSize = MAX_PATH; - Ret = RegEnumValue(hKey, dwIndex, szBuf, &dwSize, NULL, &dwType, NULL, NULL); - } - } - } - - TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwnd, NULL); - DestroyMenu(hMenu); - RegCloseKey(hKey); +ActivateLayout(ULONG uLayoutNum) +{ + HKL hKl; + TCHAR szLayoutNum[CCH_ULONG_DEC + 1]; + TCHAR szLCID[CCH_LAYOUT_ID + 1]; + DWORD Ret; + + _ultot(uLayoutNum, szLayoutNum, 10); + GetLayoutID(szLayoutNum, szLCID); + + // Switch to the new keyboard layout + hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE); + Ret = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDWININICHANGE); +} + +static HMENU +BuildPopupMenu() +{ + HMENU hMenu; + HKEY hKey; + DWORD dwIndex, dwSize; + TCHAR szLayoutNum[CCH_ULONG_DEC + 1]; + TCHAR szName[MAX_PATH]; + + hMenu = CreatePopupMenu(); + + 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(!GetLayoutName(szLayoutNum, szName)) + break; + + AppendMenu(hMenu, MF_STRING, _ttoi(szLayoutNum), szName); + } + + RegCloseKey(hKey); + } + + return hMenu; }
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { - POINT pt; - - switch (Message) - { - case WM_CREATE: - AddTrayIcon(hwnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN))); - break; - - case WM_NOTIFYICONMSG: - switch (lParam) - { - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - { - GetCursorPos(&pt); - ShowPopupMenu(hwnd, pt); - } - break; - } - break; - - case WM_COMMAND: - ActivateLayout(LOWORD(wParam)); - break; - - case WM_DESTROY: - DelTrayIcon(hwnd); - PostQuitMessage(0); - break; - } - - return DefWindowProc(hwnd, Message, wParam, lParam); + static HMENU hPopupMenu; + + 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: + { + POINT pt; + + GetCursorPos(&pt); + TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL); + } + break; + } + break; + + case WM_COMMAND: + ActivateLayout(LOWORD(wParam)); + break; + + 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; - - 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"; - - if (!RegisterClass(&WndClass)) return 0; - - hwnd = CreateWindow(L"kbswitch", L"kbswitch", 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, hInstance, NULL); + WNDCLASS WndClass = {0}; + MSG msg; + + 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"; + + if (!RegisterClass(&WndClass)) return 0; + + hwnd = CreateWindow(L"kbswitch", L"kbswitch", 0, 0, 0, 1, 1, HWND_DESKTOP, NULL, hInstance, NULL);
while(GetMessage(&msg,NULL,0,0)) {
Modified: trunk/reactos/base/applications/kbswitch/kbswitch.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/kbswitch/... ============================================================================== --- trunk/reactos/base/applications/kbswitch/kbswitch.h [iso-8859-1] (original) +++ trunk/reactos/base/applications/kbswitch/kbswitch.h [iso-8859-1] Sun Apr 20 10:48:43 2008 @@ -1,6 +1,11 @@ +#include <stdlib.h> #include <windows.h> #include <tchar.h> -#include <stdio.h> -#include <stdlib.h>
#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