如何在后台线程中使用LoadKeyboardLayout?

Far*_* H. 10 delphi tthread keyboard-layout

我正在使用LoadKeyboardLayout函数以这种方式加载和激活键盘布局:

procedure TfrmMain.eSearchEnter(Sender: TObject);
begin
  LoadKeyboardLayout('00000429', KLF_ACTIVATE);
end;
Run Code Online (Sandbox Code Playgroud)

它工作得很好,但它冻结活动形式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;
Run Code Online (Sandbox Code Playgroud)

这个后台线程我正在以这种方式运行:

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;
Run Code Online (Sandbox Code Playgroud)

问题是,它没有按预期更改键盘布局.我调试了代码并且所有行都被执行了; 只是LoadKeyboardLayout函数没有完成它的工作.

如何从后台线程使LoadKeyboardLayout函数工作?

TLa*_*ama 8

首先,您应该检查LoadKeyboardLayout函数的结果,如果失败,您应该检查GetLastError函数返回的错误以确定错误.

但即使此函数调用成功,它也会激活输入区域设置标识符,但对于您的工作线程.作为国旗的LoadKeyboardLayout参考状态KLF_ACTIVATE(由我强调):

KLF_ACTIVATE

如果尚未加载指定的输入语言环境标识符,则该函数会加载并激活当前线程的输入语言环境标识符.


虽然,如果要为整个过程加载和激活键盘布局,可以尝试将KLF_ACTIVATE标志与KLF_SETFORPROCESS一个标志组合:

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

  • +1.很好的回答,以及"KLF_ACTIVATE"的"当前线程"的好处.(我必须说我不明白海报在进入编辑控件时改变键盘布局的想法(对我来说似乎是一个非常糟糕的主意).我知道我会快速卸载这样做的应用程序.) (3认同)
  • @FarshadH:谢谢你的解释.:-)我不确定我是否同意这是用户友好的,但我可能不是你的用户群的一部分.<G> (2认同)