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(a)reactos.org)
+ * Colin Finck (mail(a)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