Я достаточно давно пользуюсь 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 или кто просто изучает программирование.
