Изменение макета клавиатуры для другого процесса

Я пишу программу на С#, которая работает в фоновом режиме, и позволяет пользователям использовать горячую клавишу для переключения раскладок клавиатуры в активном окне. (Windows поддерживает только CTRL + SHIFT и ALT + SHIFT)

Я использую RegisterHotKey, чтобы поймать горячую клавишу, и она работает нормально.

Проблема заключается в том, что я не могу найти какой-либо API для изменения раскладки клавиатуры для сфокусированного окна.

ActivateKeyboardLayout и LoadKeyboardLayout могут изменять только раскладку клавиатуры для вызывающего потока.

Кто-нибудь знает, как изменить раскладку клавиатуры для другого потока (как это делает языковая панель)?

Ответы

Ответ 1

Другой способ, который может быть приемлемым, если вы пишете что-то только для себя: определите отдельную комбинацию клавиш для каждого макета (например, Alt + Shift + 1 и т.д.) и используйте SendInput для переключения между ними.

Условия, в которых это возможно, ограничены, конечно.

Ответ 2

PostMessage(handle, 
    WM_INPUTLANGCHANGEREQUEST, 
    0, 
    LoadKeyboardLayout( StrCopy(Layout,'00000419'), KLF_ACTIVATE)
);

Ответ 3

Я думаю, что трюк заключается в том, чтобы заставить ваш код выполнять в контексте потока, раскладка клавиатуры которого вы хотите изменить. Вам нужно будет сделать несколько win32 interop здесь и узнать о DLL Injection, чтобы ваш код выполнялся в удаленном потоке.

A обработчик клавиатуры для клавиатуры выглядит для вас хорошим вариантом.

Взгляните на http://www.codeproject.com/KB/threads/winspy.aspx

Ответ 4

  function ChangeRemoteWndKeyboardLayoutToRussian(
    const RemoteHandle: THandle): Boolean;
  var
    Dumme: DWORD;
    Layout: HKL;
  begin
    Layout := LoadKeyboardLayout('00000419', KLF_ACTIVATE);
    Result := SendMessageTimeOut(RemoteHandle, WM_INPUTLANGCHANGEREQUEST,
      0, Layout, SMTO_ABORTIFHUNG, 200, Dumme) <> 0;
    if Result then    
      Result := SendMessageTimeOut(RemoteHandle, WM_INPUTLANGCHANGEREQUEST,
        RUSSIAN_CHARSET, Layout, SMTO_ABORTIFHUNG, 200, Dumme) <> 0;
  end;