interface
uses
SysUtils, Classes, Controls, StdCtrls, ExtCtrls, Dialogs;
type
KeysetInt = -1..9; //-1表示發生錯誤
TNokiaEdit = class(TCustomEdit)
private
FInterval: Integer;
FKeyset: TStrings;
procedure SetKeyset(const Value: TStrings);
function GetTimerEnabled: Boolean;
procedure SetTimerEnabled(const Value: Boolean);
function GetTextLength: Integer;
{ Private declarations }
protected
{ Protected declarations }
FTimer: TTimer;
procedure OnTimer(Sender: TObject);virtual;
property TimerEnabled: Boolean read GetTimerEnabled write SetTimerEnabled;
procedure KeyPress(var Key: Char); override;
function IndexByChar(const Key: Char): KeysetInt;
function SearchNextChar(const Index: KeysetInt; Key: Char): Char;
function SearchFirstChar(const Index: KeysetInt): Char;
function EndOfChar(const Value: string): Char;
public
{ Public declarations }
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
property TextLength: Integer read GetTextLength;
published
{ Published declarations }
property MaxLength default 1;
property Interval: Integer read FInterval write FInterval;
property Keyset: TStrings read FKeyset write SetKeyset;
property Font;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('CoolSlob', [TNokiaEdit]);
end;
{ TNokiaEdit }
constructor TNokiaEdit.Create(AOwner: TComponent);
begin
inherited;
FKeySet := TStringList.Create;
FTimer := TTimer.Create(Self);
FTimer.OnTimer := OnTimer;
end;
destructor TNokiaEdit.Destroy;
begin
FKeySet.Free;
FKeySet := nil;
inherited;
end;
function TNokiaEdit.EndOfChar(const Value: string): Char;
begin
if Value = '' then Result := #0
else Result := Value[Length(Value)];
end;
function TNokiaEdit.GetTextLength: Integer;
begin
Result := Length(Trim(Text));
end;
function TNokiaEdit.GetTimerEnabled: Boolean;
begin
Result := FTimer.Enabled;
end;
function TNokiaEdit.IndexByChar(const Key: Char): KeysetInt;
//
var
I: Integer;
begin
Result := -1;
if not Assigned(FKeyset) then Exit;
for I := 0 to FKeyset.Count - 1 do
begin
if Pos(Key, FKeyset.Strings[I]) > 0 then
begin
Result := I;
Break;
end;
end;
end;
procedure TNokiaEdit.KeyPress(var Key: Char);
var
CurIndex, NewIndex: KeysetInt;
S: string;
CurChar: Char;
Selected: Boolean;
begin
inherited;
if Key in ['0'..'9'] then
begin
FTimer.Enabled := False;
if TextLength = 0 then CurIndex := -1
else CurIndex := IndexByChar(Text[Length(Text)]);
NewIndex := Ord(Key) - 48;
if CurIndex = NewIndex then
begin
CurChar := EndOfChar(Text);
S := Text;
Selected := WordBool(SelLength);
Delete(S, SelStart + 1, SelLength);
Text := S;
if (not Selected)or(CurChar='') then Text := Text + SearchFirstChar(CurIndex)
else Text := Text + SearchNextChar(CurIndex, CurChar);
end
else
Text := Text + SearchFirstChar(NewIndex);
SelStart := Length(Text) - 1;
SelLength := 1;
FTimer.Enabled := True;
Key := #0;
end;
end;
procedure TNokiaEdit.OnTimer(Sender: TObject);
begin
SelLength := 0;
SelStart := Length(Text);
FTimer.Enabled := False;
end;
function TNokiaEdit.SearchFirstChar(const Index: KeysetInt): Char;
var
S: string;
begin
Result := #0;
S := FKeyset.Strings[Index];
if S <> '' then Result := S[1];
end;
function TNokiaEdit.SearchNextChar(const Index: KeysetInt;
Key: Char): Char;
var
I: Integer;
S: string;
begin
S := FKeyset.Strings[Index];
I := Pos(Key, S);
if I = Length(S) then I := 1
else I := I + 1;
Result := S[I];
end;
procedure TNokiaEdit.SetKeyset(const Value: TStrings);
begin
if Assigned(FKeyset) then FKeySet.Assign(Value)
else FKeyset := Value;
end;
procedure TNokiaEdit.SetTimerEnabled(const Value: Boolean);
begin
if FTimer.Enabled <> Value then
FTimer.Enabled := Value;
end;
end.