mirror of
https://github.com/reactos/reactos.git
synced 2025-05-31 15:08:14 +00:00
- 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 svn path=/trunk/; revision=33062
This commit is contained in:
parent
760ed27010
commit
6e8acacf27
2 changed files with 160 additions and 104 deletions
|
@ -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 WM_NOTIFYICONMSG (WM_USER + 248)
|
||||||
#define BUFSIZE 256
|
#define BUFSIZE 256
|
||||||
|
@ -9,13 +17,13 @@ HWND hwnd;
|
||||||
static VOID
|
static VOID
|
||||||
AddTrayIcon(HWND hwnd, HICON hIcon)
|
AddTrayIcon(HWND hwnd, HICON hIcon)
|
||||||
{
|
{
|
||||||
NOTIFYICONDATA tnid;
|
NOTIFYICONDATA tnid;
|
||||||
|
|
||||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||||
tnid.hWnd = hwnd;
|
tnid.hWnd = hwnd;
|
||||||
tnid.uID = 1;
|
tnid.uID = 1;
|
||||||
tnid.uFlags = NIF_ICON | NIF_MESSAGE;
|
tnid.uFlags = NIF_ICON | NIF_MESSAGE;
|
||||||
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
tnid.uCallbackMessage = WM_NOTIFYICONMSG;
|
||||||
tnid.hIcon = hIcon;
|
tnid.hIcon = hIcon;
|
||||||
|
|
||||||
Shell_NotifyIcon(NIM_ADD, &tnid);
|
Shell_NotifyIcon(NIM_ADD, &tnid);
|
||||||
|
@ -26,156 +34,199 @@ AddTrayIcon(HWND hwnd, HICON hIcon)
|
||||||
static VOID
|
static VOID
|
||||||
DelTrayIcon(HWND hwnd)
|
DelTrayIcon(HWND hwnd)
|
||||||
{
|
{
|
||||||
NOTIFYICONDATA tnid;
|
NOTIFYICONDATA tnid;
|
||||||
|
|
||||||
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
tnid.cbSize = sizeof(NOTIFYICONDATA);
|
||||||
tnid.hWnd = hwnd;
|
tnid.hWnd = hwnd;
|
||||||
tnid.uID = 1;
|
tnid.uID = 1;
|
||||||
|
|
||||||
Shell_NotifyIcon(NIM_DELETE, &tnid);
|
Shell_NotifyIcon(NIM_DELETE, &tnid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
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;
|
HKEY hKey;
|
||||||
DWORD dwBufLen;
|
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)
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)szBuf, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
dwBufLen = BUFSIZE;
|
dwBufLen = MAX_PATH * sizeof(TCHAR);
|
||||||
if (RegQueryValueEx(hKey,_T("Layout Text"),NULL,NULL,(LPBYTE)name,&dwBufLen) == ERROR_SUCCESS)
|
|
||||||
|
if(RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL, (LPBYTE)szName, &dwBufLen) != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
return TRUE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
ActivateLayout(INT LayoutID)
|
ActivateLayout(ULONG uLayoutNum)
|
||||||
{
|
{
|
||||||
TCHAR szLayoutID[MAX_PATH], szNewLayout[MAX_PATH];
|
HKL hKl;
|
||||||
HKEY hKey;
|
TCHAR szLayoutNum[CCH_ULONG_DEC + 1];
|
||||||
DWORD dwBufLen;
|
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)
|
// Switch to the new keyboard layout
|
||||||
{
|
hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
|
||||||
dwBufLen = MAX_PATH;
|
Ret = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDWININICHANGE);
|
||||||
if (RegQueryValueEx(hKey, szLayoutID, NULL, NULL, (LPBYTE)szNewLayout, &dwBufLen) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
MessageBox(0, szNewLayout, _T(""), MB_OK);
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static HMENU
|
||||||
ShowPopupMenu(HWND hwnd, POINT pt)
|
BuildPopupMenu()
|
||||||
{
|
{
|
||||||
HMENU hMenu;
|
HMENU hMenu;
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
DWORD dwIndex = 0, dwSize, dwType;
|
DWORD dwIndex, dwSize;
|
||||||
LONG Ret;
|
TCHAR szLayoutNum[CCH_ULONG_DEC + 1];
|
||||||
TCHAR szBuf[MAX_PATH], szPreload[MAX_PATH], szName[MAX_PATH];
|
TCHAR szName[MAX_PATH];
|
||||||
|
|
||||||
hMenu = CreatePopupMenu();
|
hMenu = CreatePopupMenu();
|
||||||
|
|
||||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"),
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||||||
0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
{
|
||||||
{
|
for(dwIndex = 0; ; dwIndex++)
|
||||||
dwSize = MAX_PATH;
|
{
|
||||||
Ret = RegEnumValue(hKey, dwIndex, szBuf, &dwSize, NULL, &dwType, NULL, NULL);
|
dwSize = sizeof(szLayoutNum);
|
||||||
if (Ret == ERROR_SUCCESS)
|
if(RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||||
{
|
break;
|
||||||
while (Ret == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
dwSize = MAX_PATH;
|
|
||||||
RegQueryValueEx(hKey, szBuf, NULL, NULL, (LPBYTE)szPreload, &dwSize);
|
|
||||||
|
|
||||||
GetLayoutName(szPreload, szName);
|
if(!GetLayoutName(szLayoutNum, szName))
|
||||||
AppendMenu(hMenu, MF_STRING, _ttoi(szBuf), szName);
|
break;
|
||||||
|
|
||||||
dwIndex++;
|
AppendMenu(hMenu, MF_STRING, _ttoi(szLayoutNum), szName);
|
||||||
|
}
|
||||||
|
|
||||||
dwSize = MAX_PATH;
|
RegCloseKey(hKey);
|
||||||
Ret = RegEnumValue(hKey, dwIndex, szBuf, &dwSize, NULL, &dwType, NULL, NULL);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
|
return hMenu;
|
||||||
DestroyMenu(hMenu);
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK
|
LRESULT CALLBACK
|
||||||
WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
POINT pt;
|
static HMENU hPopupMenu;
|
||||||
|
|
||||||
switch (Message)
|
switch (Message)
|
||||||
{
|
{
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
AddTrayIcon(hwnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN)));
|
AddTrayIcon(hwnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN)));
|
||||||
break;
|
hPopupMenu = BuildPopupMenu(hwnd);
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_NOTIFYICONMSG:
|
case WM_NOTIFYICONMSG:
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
{
|
{
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
{
|
{
|
||||||
GetCursorPos(&pt);
|
POINT pt;
|
||||||
ShowPopupMenu(hwnd, pt);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
GetCursorPos(&pt);
|
||||||
ActivateLayout(LOWORD(wParam));
|
TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_DESTROY:
|
case WM_COMMAND:
|
||||||
DelTrayIcon(hwnd);
|
ActivateLayout(LOWORD(wParam));
|
||||||
PostQuitMessage(0);
|
break;
|
||||||
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
|
INT WINAPI
|
||||||
wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
|
wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
|
||||||
{
|
{
|
||||||
WNDCLASS WndClass = {0};
|
WNDCLASS WndClass = {0};
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
hInst = hInstance;
|
hInst = hInstance;
|
||||||
|
|
||||||
WndClass.style = 0;
|
WndClass.style = 0;
|
||||||
WndClass.lpfnWndProc = (WNDPROC)WndProc;
|
WndClass.lpfnWndProc = (WNDPROC)WndProc;
|
||||||
WndClass.cbClsExtra = 0;
|
WndClass.cbClsExtra = 0;
|
||||||
WndClass.cbWndExtra = 0;
|
WndClass.cbWndExtra = 0;
|
||||||
WndClass.hInstance = hInstance;
|
WndClass.hInstance = hInstance;
|
||||||
WndClass.hIcon = NULL;
|
WndClass.hIcon = NULL;
|
||||||
WndClass.hCursor = NULL;
|
WndClass.hCursor = NULL;
|
||||||
WndClass.hbrBackground = NULL;
|
WndClass.hbrBackground = NULL;
|
||||||
WndClass.lpszMenuName = NULL;
|
WndClass.lpszMenuName = NULL;
|
||||||
WndClass.lpszClassName = L"kbswitch";
|
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))
|
while(GetMessage(&msg,NULL,0,0))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
#include <stdlib.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "resource.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
|
||||||
|
|
Loading…
Reference in a new issue