spiegel-keyman/developer/src/tike/debug/UfrmSelectSystemKeyboard.pas

381 lines
10 KiB
ObjectPascal

(*
Name: UfrmSelectSystemKeyboard
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 1 Aug 2006
Modified Date: 1 Dec 2012
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 14 Sep 2006 - mcdurdin - Fill a combo box list of system keyboards
19 Nov 2007 - mcdurdin - I1157 - const string parameters
03 May 2011 - mcdurdin - I2890 - Record diagnostic data when encountering registry errors
18 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls + Win9x support
01 Dec 2012 - mcdurdin - I3613 - V9.0 - System shadow keyboards obsolete, strip out remaining code
*)
unit UfrmSelectSystemKeyboard; // I3306
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, ExtCtrls, UfrmTike;
type
TSystemKeyboardItem = class
LayoutText: string;
LayoutFile: string;
KeyboardID: string;
Installed: Boolean;
end;
TfrmSelectSystemKeyboard = class(TTIKEForm)
cmdOK: TButton;
gridKeyboards: TStringGrid;
Label1: TLabel;
cmdCancel: TButton;
tmrResetLookup: TTimer;
lblKeyboardNotInstalled: TLabel;
procedure FormCreate(Sender: TObject);
procedure gridKeyboardsKeyPress(Sender: TObject; var Key: Char);
procedure tmrResetLookupTimer(Sender: TObject);
procedure gridKeyboardsClick(Sender: TObject);
procedure gridKeyboardsDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure gridKeyboardsDblClick(Sender: TObject);
private
FLookupText: string;
function GetSystemKeyboardName: string;
procedure SetSystemKeyboardName(Value: string);
procedure InvalidateCell(ACol, ARow: Integer);
protected
function GetHelpTopic: string; override;
public
{ Public declarations }
property SystemKeyboardName: string read GetSystemKeyboardName write SetSystemKeyboardName;
end;
function SelectSystemKeyboard(FOwner: TComponent; var FKeyboardName: string): Boolean;
function LoadSystemKeyboard(var FLoadedSystemKeyboard: Boolean; FKeyboardName: string): HKL;
procedure ClearSystemKeyboardList(keyboardlist: TStrings);
procedure FillSystemKeyboardList(keyboardlist: TStrings);
function GetSystemKeyboardIndex(keyboardlist: TStrings; id: string): Integer;
implementation
uses
Keyman.Developer.System.HelpTopics,
ErrorControlledRegistry,
RegistryKeys,
utilstr;
{$R *.DFM}
function SelectSystemKeyboard(FOwner: TComponent; var FKeyboardName: string): Boolean;
begin
Result := False;
with TfrmSelectSystemKeyboard.Create(FOwner) do
try
SystemKeyboardName := FKeyboardName;
if ShowModal = mrOk then
begin
if SystemKeyboardName = FKeyboardName then Exit;
FKeyboardName := SystemKeyboardName;
Result := True;
end;
finally
Free;
end;
end;
procedure TfrmSelectSystemKeyboard.FormCreate(Sender: TObject);
var
str: TStringList;
i: Integer;
syspath, s: string;
buf: array[0..260] of Char;
begin
inherited;
gridKeyboards.DefaultRowHeight := 16 * PixelsPerInch div 96;
GetSystemDirectory(buf, 260);
syspath := IncludeTrailingPathDelimiter(buf);
str := TStringList.Create;
with TRegistryErrorControlled.Create do // I2890
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKeyReadOnly(SRegKey_KeyboardLayouts_LM) then
begin
GetKeyNames(str);
for i := str.Count - 1 downto 0 do
if OpenKeyReadOnly('\'+SRegKey_KeyboardLayouts_LM + '\' + str[i]) then
if not ValueExists('Layout Text') then // I3613
str.Delete(i)
else
begin
s := ReadString('Layout File');
if not FileExists(syspath+s)
then str[i] := ReadString('Layout Text') + '|' + s + '|' + str[i] + '|0'
else str[i] := ReadString('Layout Text') + '|' + s + '|' + str[i] + '|1';
end;
str.Sort;
gridKeyboards.RowCount := str.Count + 1;
for i := 0 to str.Count - 1 do
begin
s := str[i];
gridKeyboards.Cells[0, i+1] := StrToken(s, '|');
gridKeyboards.Cells[1, i+1] := StrToken(s, '|');
gridKeyboards.Cells[2, i+1] := StrToken(s, '|');
gridKeyboards.Cells[3, i+1] := StrToken(s, '|');
end;
end;
gridKeyboards.Cells[0, 0] := 'Name';
gridKeyboards.Cells[1, 0] := 'Layout';
gridKeyboards.Cells[2, 0] := 'ID';
gridKeyboards.ColWidths[3] := 0;
gridKeyboards.ColWidths[1] := 100 * PixelsPerInch div 96;
gridKeyboards.ColWidths[2] := 80 * PixelsPerInch div 96;
gridKeyboards.ColWidths[0] := gridKeyboards.ClientWidth - (100 * PixelsPerInch div 96) -
(80 * PixelsPerInch div 96) - 2;
finally
str.Free;
Free;
end;
end;
function TfrmSelectSystemKeyboard.GetHelpTopic: string;
begin
Result := SHelpTopic_Context_SelectSystemKeyboard;
end;
function TfrmSelectSystemKeyboard.GetSystemKeyboardName: string;
begin
Result := gridKeyboards.Cells[2, gridKeyboards.Row];
end;
procedure TfrmSelectSystemKeyboard.SetSystemKeyboardName(Value: string);
var
i: Integer;
begin
for i := 1 to gridKeyboards.RowCount - 1 do
if gridKeyboards.Cells[2, i] = Value then
begin
gridKeyboards.Row := i;
Exit;
end;
end;
procedure TfrmSelectSystemKeyboard.gridKeyboardsKeyPress(Sender: TObject; var Key: Char);
var
i, n: Integer;
begin
tmrResetLookup.Enabled := False;
if Key = #8 then
begin
if FLookupText <> '' then Delete(FLookupText, 1, 1);
n := Length(FLookupText);
for i := 1 to gridKeyboards.RowCount - 1 do
if Copy(gridKeyboards.Cells[0, i], 1, n) = FLookupText then
begin
gridKeyboards.Row := i;
tmrResetLookup.Enabled := True;
Exit;
end;
end
else
begin
n := Length(FLookupText) + 1;
for i := 1 to gridKeyboards.RowCount - 1 do
if UpperCase(Copy(gridKeyboards.Cells[0, i], 1, n)) = FLookupText + UpCase(Key) then
begin
FLookupText := FLookupText + UpCase(Key);
gridKeyboards.Row := i;
InvalidateCell(0, gridKeyboards.Row);
gridKeyboards.Update;
tmrResetLookup.Enabled := True;
Exit;
end;
end;
tmrResetLookup.Enabled := True;
end;
procedure TfrmSelectSystemKeyboard.tmrResetLookupTimer(Sender: TObject);
begin
FLookupText := '';
tmrResetLookup.Enabled := False;
InvalidateCell(0, gridKeyboards.Row);
gridKeyboards.Update;
end;
procedure TfrmSelectSystemKeyboard.gridKeyboardsClick(Sender: TObject);
begin
cmdOK.Enabled := gridKeyboards.Cells[3, gridKeyboards.Row] = '1';
lblKeyboardNotInstalled.Visible := not cmdOK.Enabled;
end;
procedure TfrmSelectSystemKeyboard.gridKeyboardsDrawCell(Sender: TObject;
ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var
w: Integer;
begin
with gridKeyboards.Canvas do
begin
Font := gridKeyboards.Font;
if gdFixed in State then
begin
Brush.Color := clBtnFace;
Font.Color := clBtnText;
end
else if gdSelected in State then
begin
Brush.Color := clHighlight;
Font.Color := clHighlightText;
end
else
begin
Brush.Color := clWindow;
Font.Color := clWindowText;
end;
if gridKeyboards.Cells[3, ARow] = '0' then Font.Color := clGrayText;
Brush.Style := bsSolid;
FillRect(Rect);
TextRect(Rect, Rect.Left+2, Rect.Top+2, gridKeyboards.Cells[ACol, ARow]);
if (FLookupText <> '') and (gdSelected in State) and (ACol = 0) then
begin
w := TextWidth(Copy(gridKeyboards.Cells[ACol, ARow], 1, Length(FLookupText)));
Pen.Color := clBlack;
Pen.Width := 2;
MoveTo(w+2, Rect.Top);
LineTo(w+2, Rect.Bottom-1);
end;
end;
end;
procedure TfrmSelectSystemKeyboard.InvalidateCell(ACol, ARow: Integer);
var
r: TRect;
begin
r := gridKeyboards.CellRect(ACol, ARow);
InvalidateRect(gridKeyboards.Handle, @r, False);
end;
procedure TfrmSelectSystemKeyboard.gridKeyboardsDblClick(Sender: TObject);
begin
if cmdOK.Enabled then ModalResult := mrOk;
end;
procedure ClearSystemKeyboardList(keyboardlist: TStrings);
var
i: Integer;
begin
for i := 0 to keyboardlist.Count - 1 do
keyboardlist.Objects[i].Free;
keyboardlist.Clear;
end;
procedure FillSystemKeyboardList(keyboardlist: TStrings);
var
buf: array[0..260] of char;
syspath: string;
str: TStringList;
i: Integer;
k: TSystemKeyboardItem;
begin
keyboardlist.BeginUpdate;
ClearSystemKeyboardList(keyboardlist);
GetSystemDirectory(buf, 260);
syspath := IncludeTrailingPathDelimiter(buf);
str := TStringList.Create;
with TRegistryErrorControlled.Create do // I2890
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKeyReadOnly(SRegKey_KeyboardLayouts_LM) then
begin
GetKeyNames(str);
for i := str.Count - 1 downto 0 do
if OpenKeyReadOnly('\'+SRegKey_KeyboardLayouts_LM + '\' + str[i]) then
if not ValueExists('Layout Text') then // I3613
str.Delete(i)
else
begin
k := TSystemKeyboardItem.Create;
k.LayoutText := ReadString('Layout Text');
k.LayoutFile := ReadString('Layout File');
k.Installed := FileExists(syspath+k.LayoutFile);
k.KeyboardID := str[i];
keyboardlist.AddObject(k.LayoutText + ' ('+k.LayoutFile+')', k);
end;
str.Assign(keyboardlist);
str.Sort;
keyboardlist.Assign(str);
end;
finally
str.Free;
Free;
end;
keyboardlist.EndUpdate;
end;
function LoadSystemKeyboard(var FLoadedSystemKeyboard: Boolean; FKeyboardName: string): HKL;
type
PHKL = ^HKL;
var
h: HKL;
hq, hp: PHKL;
i, n: Integer;
begin
{ Load the layout (if not already loaded) and determine if it should be unloaded again }
n := GetKeyboardLayoutList(0, hp);
hp := PHKL(AllocMem(n * sizeof(HKL)));
try
GetKeyboardLayoutList(n, hp^);
h := LoadKeyboardLayout(PChar(FKeyboardName), 0);
hq := hp;
FLoadedSystemKeyboard := True;
for i := 0 to n - 1 do
if hq^ = h
then begin FLoadedSystemKeyboard := False; Break; end
else Inc(hq);
finally
FreeMem(hp);
end;
Result := h;
end;
function GetSystemKeyboardIndex(keyboardlist: TStrings; id: string): Integer;
var
i: Integer;
begin
for i := 0 to keyboardlist.Count - 1 do
if (keyboardlist.Objects[i] is TSystemKeyboardItem) and (TSystemKeyboardItem(keyboardlist.Objects[i]).KeyboardID = id) then
begin
Result := i;
Exit;
end;
Result := -1;
end;
end.