10

I'm using the LoadKeyboardLayout function to load and activate the keyboard layout this way:

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

It works perfectly, but it freezes the active form for 1-2 seconds, since this change takes some time. For preventing this, I've moved this code to a background thread like this:

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;

This background thread I'm then running this way:

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;

The problem is, that it doesn't change the keyboard layout as expected. I've debugged the code and all lines were execeuted; just the LoadKeyboardLayout function hasn't made its job.

How can I make the LoadKeyboardLayout function work from a background thread ?

TLama
  • 75,147
  • 17
  • 214
  • 392
Farshad H.
  • 303
  • 4
  • 16

1 Answers1

8

First of all, you should check the result of the LoadKeyboardLayout function and if it fails, you should check the error returned by the GetLastError function to determine what is wrong.

But even if this function call succeed, it will activate the input locale identifier, but for your worker thread. As the LoadKeyboardLayout reference states for the KLF_ACTIVATE flag (emphasized by me):

KLF_ACTIVATE

If the specified input locale identifier is not already loaded, the function loads and activates the input locale identifier for the current thread.


Although, if you want to load and activate keyboard layout for the whole process, you may try to combine the KLF_ACTIVATE flag with the KLF_SETFORPROCESS one:

const
  KLF_SETFORPROCESS = $00000100;
begin
  if LoadKeyboardLayout('00000429', KLF_ACTIVATE or KLF_SETFORPROCESS) = 0 then
    RaiseLastOSError;
end;
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Thanks, i should guess! how i can fix this? – Farshad H. Dec 09 '12 at 06:11
  • I was checked the result, and it never returns NUL. how i can apply this function to active control (like a TEdit)? – Farshad H. Dec 09 '12 at 06:22
  • 1
    If you're going to change the keyboard layout for the process (what I guess you do, the worker thread you've used since it takes a long time, don't you ?), try to combine the `KLF_ACTIVATE` flag with the `KLF_SETFORPROCESS` one. – TLama Dec 09 '12 at 06:26
  • 3
    +1. Nice answer, and nice catch of the `current thread` for `KLF_ACTIVATE`. (I must say I don't understand the poster's thought of changing the keyboard layout when entering an edit control (seems like a really bad idea to me). I know I'd quickly uninstall an app that did that.) – Ken White Dec 09 '12 at 06:33
  • @TLama Yes, exactly, i want kill that 1-2sec delay time for changing keyboard layout, i want it change immediately. – Farshad H. Dec 09 '12 at 06:54
  • @KenWhite Dear friend, I have a multilingual form that user should fill fields by different languages. the user can change language him/herself with Alt+Shift (or etc methods), but i trying to do it automatically by software when user enters a field. I want my software change input language automatically for user-friendly purposes. – Farshad H. Dec 09 '12 at 07:02
  • 2
    @FarshadH: Thanks for the explanation. :-) I'm not sure I agree that it's user-friendly, but then I'm probably not part of your user base. – Ken White Dec 09 '12 at 07:04
  • @TLama Thank you for your advise, I used **KLF_SETFORPROCESS**, and it works! thanks a lot dear friend :) – Farshad H. Dec 09 '12 at 07:13
  • @TLama Sure, I was try do it, but I'm new to http://stackoverflow.com and i need 15 reputation for this, i will do it gladly as soon as possible :) – Farshad H. Dec 09 '12 at 07:25
  • @jachguate HiiiiHaaaaa :D u sweet :-* – Farshad H. Dec 09 '12 at 07:33