Не знаю кому-как, а мне было очень интересно, как же это во многих программах в StatusBar’ах ставят кнопки, или какие ни-ть иконки. Долго я лазил по интернету, качалу кучу компонент, но когда я ставил на форму такую панельку, кроме нее в довесок шла огромная библиотека, которая солидно накидала “лишних килограмм” моей программе. Потом я нашел в какой то литературе, как сделать StatusBar, к которому можна цеплять контролы. После этого я не использую огромных компнент для того, чтобы сделать в своей программе statusbar чукточку круче. Оказывается что если создать свой статусбар на основе стандартного и поменять его конструктор Create, то получится как раз то, что мне нужно J:
Рисунок 1.
unit MStatusBar;
interface
uses ComCtrls, Classes, Controls;
{$ObjExportAll On}
type
TMyStatusBar = class(TStatusBar)
public
constructor Create(AOwner: TComponent); override;
end;
procedure Register;
implementation
uses Consts;
constructor TMyStatusBar.Create( AOwner : TComponent );
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csAcceptsControls];
end;
procedure Register;
begin
RegisterComponents('Win32', [TMyStatusBar]);
end;
end.
Если вот такой юнит проинсталлировать как компоненту, то потом его можна использовать в своих программах ;)
Вы спросите к чему это я клоню?
А идея этой статьи – создание своего индикатора клавиатуры, который будет сидеть именно в таком статус баре J
Долго я копал по разным конференциям и FAQ’ах.. но все таки нашел как это делается, теперь всегда это использую для наглядности и эргономики в программах J
Значит чтобы получить текущую расскладку клавиатуры нужно использовать функцию GetKeyboardLayoutName, за реакцию на изменение расскладки клавиатуры отвечает Windows Message - WM_INPUTLANGCHANGEREQUEST и WM_INPUTLANGCHANGE
Они активируются при запросе на изменение расскладки и изменении расскладки соответственно. Но на практике оказалось, что активируются эти сообщения перед изменением текущей рассскладки, от этого и будем копать: Я избавился от такого очень просто: поставил на форму деактивированый таймер, который включается по меседжах, описаных раньше и через 10 миллисекунд спрашиваю у системмы текущую расскладку (после этого он опять деактивируется). Кстати чтобы знать активные в системме локалы можна порыться в реестре (так как это делал я J)
Для иконки я использовал TAnimatedImage из поставки RXLib, потому что и в него наиболее просто засунуть несколько пиктограм да и получить их тоже не сложно ;).
ИТАК: При создании формы
procedure TForm1.FormCreate(Sender: TObject);
begin
application.OnMessage:=LangChange;
end;
Рисунок 2.
Процедура, которая ловит изменение и запускает таймер
procedure Tform1.LangChange(var m:TMsg;var Handled: Boolean);
begin
if (m.message=WM_INPUTLANGCHANGEREQUEST) or
(m.message=WM_INPUTLANGCHANGE) then
Begin
langtimer.enabled:=true;
end;
end;
Собственно сам таймер:
procedure TForm1.LangTimerTimer(Sender: TObject);
var
szBuf : array[0..KL_NAMELENGTH] of Char;
begin
GetKeyboardLayoutName( @(szBuf[0]) );
if string(szbuf)='00000409'then
begin
flag.Glyphnum:=2;
flag.Hint:='Язык: Английский';
end
else
if string(szbuf)='00000419'then
Begin
flag.Glyphnum:=1;
flag.Hint:='Язык: Русский';
end
else
if string(szbuf)='00000422'then
Begin
flag.Glyphnum:=0;
flag.Hint:='Язык: Украинский';
end
else
Begin
flag.Glyphnum:=3;
flag.Hint:='Неизвестный язык :(';
end;
langtimer.Enabled:=false;
end;
Вот вроде все на счет индикатора, но когда есть индикатор, то хочется еще самому програмно переключать расскладки клавиатуры J а это делается очень просто: за это отвечает функция LoadKeyboardLayout . её и будем использовать:
Procedure ChangeLanguage(Language:String);
var
LangName : array[0..KL_NAMELENGTH] of Char;
begin
StrCopy(LangName,pchar(Language));
LoadKeyboardLayout(LangName,KLF_ACTIVATE);
end;
P.S.Маленький список языковых расскладок:
Ukrainian='00000422';
Russian ='00000419';
English ='00000409';
German ='00000407';
Spanish ='00000403';
polish ='00000415';
Romainan ='00000418';
French ='0000040C';