Как использовать LoadKeyboardLayout в фоновом потоке?

Я использую LoadKeyboardLayout для загрузки и активации раскладки клавиатуры следующим образом:

procedure TfrmMain.eSearchEnter(Sender: TObject);
begin
  LoadKeyboardLayout('00000429', KLF_ACTIVATE);
end;

Он работает отлично, но он замораживает активную форму на 1-2 секунды, так как это изменение занимает некоторое время. Чтобы предотвратить это, я переместил этот код в фоновый поток следующим образом:

type
  FLangChangeThread = class(TThread)
  private
    FLang: string;
  protected
    procedure Execute; override;
  public
    property Lang: string read FLang write FLang;
  end;

implementation

procedure FLangChangeThread.Execute;
begin
  if FLang = 'EN' then
    LoadKeyboardLayout('00000409', KLF_ACTIVATE)
  else
  if FLang = 'FA' then
    LoadKeyboardLayout('00000429', KLF_ACTIVATE);
end;

Этот фоновый поток я запускаю следующим образом:

procedure TfrmMain.ChangeWritingLanguage(ALang: string);
begin
  with FLangChangeThread.Create(True) do
  begin
    FreeOnTerminate := True;
    Lang := ALang;
    Resume;
  end;
end;

procedure TfrmMain.eSearchEnter(Sender: TObject);
begin
  ChangeWritingLanguage('FA');
end;

Проблема заключается в том, что она не меняет раскладку клавиатуры, как ожидалось. Я отлаживал код, и все строки были execeuted; только функция LoadKeyboardLayout не выполнила свою работу.

Как я могу заставить LoadKeyboardLayout работать из фонового потока?

Ответ 1

Прежде всего, вы должны проверить результат LoadKeyboardLayout, и если это не удается, вы должны проверить ошибку, возвращаемую GetLastError, чтобы определить, что не так.

Но даже если вызов этой функции будет успешным, он активирует идентификатор локали ввода, но для рабочего потока. Поскольку LoadKeyboardLayout ссылается на KLF_ACTIVATE флаг (подчеркнуто мной):

KLF_ACTIVATE

Если указанный идентификатор языка ввода еще не загружен, функция загружает и активирует идентификатор локали ввода для текущий поток.


Хотя, если вы хотите загрузить и активировать раскладку клавиатуры для всего процесса, вы можете попытаться объединить флаг KLF_ACTIVATE с помощью KLF_SETFORPROCESS one:

const
  KLF_SETFORPROCESS = $00000100;
begin
  if LoadKeyboardLayout('00000429', KLF_ACTIVATE or KLF_SETFORPROCESS) = 0 then
    RaiseLastOSError;
end;