Я достаточно давно пользуюсь OS X и привык к его удобной системе переключения языков. Отличие от переключения в Windows состоит в том, что на маке переключение языков происходит между двумя последними использовавшимися. До тех пор, пока в Windows два языка — это не создает проблем, но лично я знаю людей, у которых 4 языка это норма и для них переключение языков доставляет некоторые неудобства из-за чего выбирать нужный язык приходится кликом мышки, а не комбинацией кнопок. И вот так, после очередного удаления/установки третьего языка, было решено написать простой переключатель раскладки клавиатуры для себя, а заодно получить полезный опыт.
Исходники программы доступны по адресу https://bitbucket.org/Ezbar/languageswitcher/overview. Для тех кто хочет попробовать программу и не заниматься компиляцией найдут бинарник в разделе Downloads.
Какие задачи пришлось решать:
— перехват нажатий комбинации Win + Пробел
— смена раскладки для активной программы
— пропадание фокуса активной программы, после смены раскладки
Рассмотрим каждый случай отдельно. Для перехвата нажатий мы будем использовать функции API и установим хук для WH_KEYBOARD_LL. Значение констант и всю обвязку вызова хука можно посмотреть в коде.
Смена раскладки для активной программы так же производится через вызов API функцией PostMessage. Для этого мы получаем дискриптор активного приложения и отправляем ему сообщение для смены раскладки. Шестнадцатеричный код для кодировки языка мы получаем из функции ответственной за получение всех установленных языков в систему и их порядок переключения.
Пропадание фокуса активной программы можно было наблюдать при вводе текста, например, в адресной строке браузера. После переключения языка пропадал фокус в текстом поле, где происходил набор. Оказалось что это очень просто исправляется в конструкторе.
В итоге я получил хороший опыт и маленькую, но полезную программу, которая облегчает жизнь, если у вас установлено больше двух ракладок клавиатуры. Буду признателен за любые комментарии и советы и прошу прощение за допущенные мною орфографические ошибки, а так же за возможно сумбурное изложение мыслей. Автор самоучка и, возможно, некоторые вещи называет не своими именами. Всем спасибо за внимание. Надеюсь, публикация будет кому-то полезной, например у кого на одном компьютере живет OSX+Windows или кто просто изучает программирование.
Исходники программы доступны по адресу https://bitbucket.org/Ezbar/languageswitcher/overview. Для тех кто хочет попробовать программу и не заниматься компиляцией найдут бинарник в разделе Downloads.
Какие задачи пришлось решать:
— перехват нажатий комбинации Win + Пробел
— смена раскладки для активной программы
— пропадание фокуса активной программы, после смены раскладки
Рассмотрим каждый случай отдельно. Для перехвата нажатий мы будем использовать функции API и установим хук для WH_KEYBOARD_LL. Значение констант и всю обвязку вызова хука можно посмотреть в коде.
Функция проверки нажатия комбинации для переключения языка
static IntPtr IgnoreWin_Space(int nCode, IntPtr wParam, IntPtr lParam)
{
Boolean spacePressed = false;
var keyInfo = (KbHookParam)Marshal.PtrToStructure(lParam, typeof(KbHookParam));
if (nCode == HC_ACTION)
{
if ((int)wParam == WM_KEYDOWN)
{
if (keyInfo.VkCode == (int)Keys.Space)
{
spacePressed = true;
kSpace = true;
}
else
kSpace = false;
// нажат одновременно левый виндовс
if (GetAsyncKeyState(Keys.LWin) < 0)
kWin = true;
else
{
kWin = false;
}
if (kWin && kSpace)
{
if (spacePressed)
{
Bar.SetLanguage("");
Bar.Show(); // сбивает фокус, пофиксим в конструкторе
return (IntPtr)1; //just ignore the key press
}
}
}
}
if ((int)wParam == WM_KEYUP)
{
if (keyInfo.VkCode == (int)Keys.LWin)
{
kWin = false;
Bar.DoHide();
string HEX = Bar.getHex();
uint WM_INPUTLANGCHANGEREQUEST = 0x0050;
uint KLF_ACTIVATE = 1;
PostMessage(GetForegroundWindow(), WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, LoadKeyboardLayout(HEX, KLF_ACTIVATE));
}
}
return CallNextHookEx(HookHandle, nCode, wParam, lParam);
}
Смена раскладки для активной программы так же производится через вызов API функцией PostMessage. Для этого мы получаем дискриптор активного приложения и отправляем ему сообщение для смены раскладки. Шестнадцатеричный код для кодировки языка мы получаем из функции ответственной за получение всех установленных языков в систему и их порядок переключения.
Смена раскладки для активной программы
string HEX = Bar.getHex();
uint WM_INPUTLANGCHANGEREQUEST = 0x0050;
uint KLF_ACTIVATE = 1;
PostMessage(GetForegroundWindow(), WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, LoadKeyboardLayout(HEX, KLF_ACTIVATE));
Пропадание фокуса активной программы можно было наблюдать при вводе текста, например, в адресной строке браузера. После переключения языка пропадал фокус в текстом поле, где происходил набор. Оказалось что это очень просто исправляется в конструкторе.
Код для конструктора
// Show a Form without stealing focus
protected override bool ShowWithoutActivation
{
get { return true; }
}
В итоге я получил хороший опыт и маленькую, но полезную программу, которая облегчает жизнь, если у вас установлено больше двух ракладок клавиатуры. Буду признателен за любые комментарии и советы и прошу прощение за допущенные мною орфографические ошибки, а так же за возможно сумбурное изложение мыслей. Автор самоучка и, возможно, некоторые вещи называет не своими именами. Всем спасибо за внимание. Надеюсь, публикация будет кому-то полезной, например у кого на одном компьютере живет OSX+Windows или кто просто изучает программирование.