В библиотеке .NET для работы с языком ввода существует класс InputLanguage. Ранее, при разработке программ под Win32 для переключения, загрузки и определения языка ввода использовались WINAPI-функции типа GetKeyboardLayout, LoadKeyboardLayout и ActivateKeyboardLayout, а также некоторые другие. На сегодняшний день разработчики под .NET могут не заморачиваться с использованием функций WINAPI. Давайте подробнее рассмотрим класс InputLanguage и определим чего в нем все таки не хватает для полного боекомплекта.
Класс InputLanguage
Итак, описываемый класс находится в сборке System.Windows.Forms, не поддерживает наследование (описан с модификатором sealed). Поля, которые необходимы для установки, определения и переключения языка ввода, статические. В самом объекте, основанного на классе InputLanguage, хранится характеристика какого-либо языка.
Основные поля:
- статическое поле CurrentInputLanguage – задает или возвращает язык ввода для текущего потока. Содержит: Culture – хранится полная характеристика текущего языка ввода; Handle – числовой код языка, который можно подставлять в функцию WINAPI ActivateKeyboardLayout, для переключения на нужную локаль; LayoutName – содержит имя текущей раскладки клавиатуры;
- статическое поле DefaultInputLanguage – содержит информацию об установленным по умолчанию в системе языке ввода. Содержит все то же, что и предыдущее поле;
- статическое поле InstalledInputLanguages – возвращает коллекцию объектов InputLanguage. Коллекцию можно перебрать таким вот образом:
1 |
string info = string.Empty; |
2 |
InputLanguageCollection installedLangs = InputLanguage.InstalledInputLanguages; |
3 |
foreach (InputLanguage lang in installedLangs) |
5 |
info = lang.Culture.Name + " " + lang.LayoutName; |
С помощью статического метода FromCulture можно получить язык ввода ассоциирующийся с заданной культурой. Используется следующим образом:
2 |
InputLanguage lang = InputLanguage.FromCulture(new CultureInfo("ru-RU")); |
4 |
InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new CultureInfo("ru-RU")); |
Работать с классом InputLanguage удобно, но в нем отсутствуют некоторые возможности. К примеру, нельзя переключить на следующий или предыдущий язык. А так, как класс рассчитан только для работы с текущим потоком (т.е. текущим приложением), то нельзя переключить язык ввода для чужого приложения. Как решаются эти две задачи:
1. Для переключения на следующий или предыдущий язык ввода используется WINAPI-функция ActivateKeyboardLayout следующим образом:
1 |
const int HLK_NEXT = 1; |
2 |
const int HLK_PREV = 0; |
4 |
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] |
5 |
public static extern IntPtr ActivateKeyboardLayout(int hkl, uint uFlags); |
9 |
ActivateKeyboardLayout(HLK_PREV, 0); |
11 |
ActivateKeyboardLayout(HLK_NEXT, 0); |
2. Для переключения языка для чужого приложения нужно знать его хэндл и отправить ему сообщение, что было переключение языка ввода (а как он был переключен, с помощью кнопок или трея – не важно). Хэндл окна можно получить разными способами, один из них – GetForegroundWindow. Смотрим код:
1 |
[DllImport("user32.dll")] |
2 |
public static extern IntPtr GetForegroundWindow(); |
4 |
[DllImport("user32.dll", CharSet = CharSet.Auto)] |
5 |
public static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam); |
9 |
PostMessage(GetForegroundWindow(), 0x0050, 2, 0); |
Что можно сделать чтобы ваше приложение перехватывала, что был переключен язык ввода? При переключении система отправляет вашему приложению сообщение WM_INPUTLANGCHANGEREQUEST. Вам нужно его перехватить и обработать. Обрабатывать это и все остальные сообщения можно, прописав в коде нужно формы вашей программы следующий код:
1 |
protected override void WndProc(ref Message m) |
3 |
const int WM_INPUTLANGCHANGEREQUEST = 0x0050; |
5 |
if (m.Msg == WM_INPUTLANGCHANGEREQUEST) |
7 |
MessageBox.Show("Переключился язык ввода"); |
Когда я писал код выше, в моем приложении он не работал. Хотя должен. Попробуйте, может у вас получится.
Как альтернатива этому коду я в конструкторе класса формы подписался на событие InputLanguageChanged:
4 |
this.InputLanguageChanged += new InputLanguageChangedEventHandler(languageChange); |
7 |
private void languageChange(Object sender, InputLanguageChangedEventArgs e) |
9 |
MessageBox.Show("Переключился язык ввода"); |