procedure TForm1.tmWaitTimer(Sender: TObject);
var
ActiveWindow: HWND;
ActiveThreadID: DWord;
KeyBoardLayOut: HKL;
Lang: array[0..2] of Char;
KeyState: Integer;
LangStr: String;
begin
//turn on/off our "leds", similar to the keyboard leds for Num Lock, Caps Lock, Scroll Lock
im.GetBitmap(GetState(VK_NUMLOCK), imNumLock.Picture.Bitmap);
im.GetBitmap(GetState(VK_CAPITAL), imCapsLock.Picture.Bitmap);
im.GetBitmap(GetState(VK_SCROLL), imScrollLock.Picture.Bitmap);
//get foreground window, the window attached to the calling thread that gets input
ActiveWindow := GetForegroundWindow;
//get active thread ID
ActiveThreadID := GetWindowThreadProcessId(ActiveWindow, nil);
if (ActiveThreadID <> OldActiveThreadID) and (ActiveThreadID <> GetCurrentThreadID) then
begin
//detach old
AttachThreadInput(GetCurrentThreadID, OldActiveThreadID, False);
//attach thread input, for system processes this is not possible(ActiveThreadID --> 0)
if not AttachThreadInput(GetCurrentThreadID, ActiveThreadID, True) then
ActiveThreadID := 0;
//reset old threadid
OldActiveThreadID := ActiveThreadID;
end;
if ActiveThreadID > 0 then
begin
//get kebyoard layout and language with the
KeyBoardLayOut := GetKeyboardLayout(ActiveThreadID);
GetLocaleInfo(LoWord(KeyBoardLayOut), LOCALE_SENGLANGUAGE, Lang, 2);
if Length(Lang) > 0 then
begin
SetString(LangStr, PChar(@Lang[0]), Length(Lang));
LangStr := LeftStr(UpperCase(LangStr), 2);
end;
end;
//get keystate
KeyState := GetKeyState(VK_SCROLL);
//togle scroll lock according to the specification
if ((OldLangStr = 'EN') and (LangStr <> 'EN') and (KeyState = 0)) or
((OldLangStr <> 'EN') and (LangStr= 'EN') and (KeyState = 1)) or
((OldLangStr <> 'EN') and (LangStr <> 'EN') and (KeyState = 0)) or
((OldLangStr = 'EN') and (LangStr = 'EN') and (KeyState = 1)) then
SetState(VK_SCROLL, 45);
//reset old langugage string
if OldLangStr <> LangStr then
OldLangStr := LangStr;
end;