📄 jvqautocomplete.pas
字号:
{******************************************************************************}
{* WARNING: JEDI VCL To CLX Converter generated unit. *}
{* Manual modifications will be lost on next release. *}
{******************************************************************************}
{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvAutoComplete.pas, released on 2004-09-04.
The Initial Developer of the Original Code is Andreas Hausladen [Andreas dott Hausdaden att gmx dott de]
Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen.
All Rights Reserved.
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvQAutoComplete.pas,v 1.4 2005/02/06 14:06:00 asnepvangers Exp $
unit JvQAutoComplete;
{$I jvcl.inc}
interface
uses
QWindows,
SysUtils, Classes, QControls, QStdCtrls;
type
{ TControlAutoComplete implements a autocomplete code for a controls it is a
abstract base class. After you have created an instance of a derived class
you must either assign the AutoCompleteEvent to the OnKeyPress event of the
control or you must call the AutoComplete method from in a KeyPress event
handler.
(ahuser) 2005-01-31: changed from TObject to TComponent due to Notification()
Do not register this component it is more a "TObject" than a TComponent. }
TJvControlAutoComplete = class(TComponent)
private
FFilter: string;
FLastTime: Cardinal;
FMaxFilterTime: Cardinal;
FListSearch: Boolean;
FActive: Boolean;
FOnDropDown: TNotifyEvent;
FOnValidateItems: TNotifyEvent;
FOnChange: TNotifyEvent;
FOnValueChange: TNotifyEvent;
protected
function GetText: TCaption; virtual; abstract;
procedure SetText(const Value: TCaption); virtual; abstract;
procedure GetEditSel(out StartPos, EndPos: Integer); virtual; abstract;
procedure SetEditSel(StartPos, EndPos: Integer); virtual; abstract;
procedure SetItemIndex(Index: Integer); virtual; abstract;
function GetItemIndex: Integer; virtual; abstract;
function FindItemPrefix(IndexStart: Integer; const Prefix: string): Integer; virtual; abstract;
function GetItemAt(Index: Integer): string; virtual; abstract;
function GetActive: Boolean; virtual;
procedure SetFilter(const Value: string);
procedure DoDropDown; dynamic;
procedure DoValidateItems; dynamic;
procedure DoChange; dynamic;
procedure DoValueChange; dynamic;
public
constructor Create; reintroduce;
procedure AutoCompleteEvent(Sender: TObject; var Key: Char);
procedure AutoComplete(var Key: Char); virtual;
property ListSearch: Boolean read FListSearch write FListSearch; // no edit possible
property MaxFilterTime: Cardinal read FMaxFilterTime write FMaxFilterTime; // only with ListSearch
property Active: Boolean read GetActive write FActive;
property OnDropDown: TNotifyEvent read FOnDropDown write FOnDropDown;
property OnValidateItems: TNotifyEvent read FOnValidateItems write FOnValidateItems;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnValueChange: TNotifyEvent read FOnValueChange write FOnValueChange;
end;
TJvBaseEditListAutoComplete = class(TJvControlAutoComplete)
private
FEditCtrl: TCustomEdit;
FList: TStrings;
procedure SetEditCtrl(Value: TCustomEdit);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function GetText: TCaption; override;
procedure SetText(const Value: TCaption); override;
procedure GetEditSel(out StartPos, EndPos: Integer); override;
procedure SetEditSel(StartPos, EndPos: Integer); override;
function FindItemPrefix(IndexStart: Integer; const Prefix: string): Integer; override;
function GetItemAt(Index: Integer): string; override;
function GetActive: Boolean; override;
property List: TStrings read FList write FList;
public
constructor Create(AEditCtrl: TCustomEdit; AList: TStrings);
destructor Destroy; override;
property EditCtrl: TCustomEdit read FEditCtrl write SetEditCtrl;
end;
{ TEditListAutoComplete implements a autocomplete code for a Edit/TStrings
pair. After you have created an instance of this class you must either
assign the AutoCompleteEvent to the OnKeyPress event of the edit control
or you must call the AutoComplete method from in a KeyPress event handler. }
TJvEditListAutoComplete = class(TJvBaseEditListAutoComplete)
private
FOnItemIndexChange: TNotifyEvent;
FOnValidateItemIndex: TNotifyEvent;
public
FItemIndex: Integer;
function GetList: TStrings;
procedure SetList(Value: TStrings);
procedure SetInternalItemIndex(Value: Integer);
protected
procedure SetItemIndex(Index: Integer); override;
function GetItemIndex: Integer; override;
public
constructor Create(AEditCtrl: TCustomEdit; AList: TStrings);
property ItemIndex: Integer read FItemIndex write SetInternalItemIndex;
property List: TStrings read GetList write SetList;
property OnItemIndexChange: TNotifyEvent read FOnItemIndexChange write FOnItemIndexChange;
property OnValidateItemIndex: TNotifyEvent read FOnValidateItemIndex write FOnValidateItemIndex;
end;
{ TEditListBoxAutoComplete implements a autocomplete code for a Edit/ListBox
pair. After you have created an instance of this class you must either
assign the AutoCompleteEvent to the OnKeyPress event of the edit control
or you must call the AutoComplete method from in a KeyPress event handler. }
TJvEditListBoxAutoComplete = class(TJvBaseEditListAutoComplete)
private
FListBox: TCustomListBox;
procedure SetListBox(Value: TCustomListBox);
protected
procedure SetItemIndex(Index: Integer); override;
function GetItemIndex: Integer; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
constructor Create(AEditCtrl: TCustomEdit; AListBox: TCustomListBox);
destructor Destroy; override;
property ListBox: TCustomListBox read FListBox write SetListBox;
end;
{ TComboBoxAutoComplete implements a autocomplete code for a ComboBox.
After you have created an instance of this class you must either assign the
AutoCompleteEvent to the OnKeyPress event of the edit control or you must
call the AutoComplete method from in a KeyPress event handler. }
TJvComboBoxAutoComplete = class(TJvControlAutoComplete)
private
FComboBox: TCustomComboBox;
procedure SetComboBox(Value: TCustomComboBox);
protected
function GetText: TCaption; override;
procedure SetText(const Value: TCaption); override;
procedure GetEditSel(out StartPos, EndPos: Integer); override;
procedure SetEditSel(StartPos, EndPos: Integer); override;
procedure SetItemIndex(Index: Integer); override;
function GetItemIndex: Integer; override;
function FindItemPrefix(IndexStart: Integer; const Prefix: string): Integer; override;
function GetItemAt(Index: Integer): string; override;
function GetActive: Boolean; override;
public
constructor Create(AComboBox: TCustomComboBox);
property ComboBox: TCustomComboBox read FComboBox write SetComboBox;
end;
TJvLookupAutoCompleteKind = (akListBox, akStrings);
TJvLookupAutoComplete = class(TComponent)
private
FAutoComplete: TJvEditListAutoComplete;
FListBox: TCustomListBox;
FStrings: TStrings;
FKind: TJvLookupAutoCompleteKind;
FOrgKeyPress: TKeyPressEvent;
FOnChange: TNotifyEvent;
FOnValidateStrings: TNotifyEvent;
FOnDropDown: TNotifyEvent;
FOnValueChange: TNotifyEvent;
function GetEdit: TCustomEdit;
function GetItemIndex: Integer;
function GetListSearch: Boolean;
procedure SetEdit(Value: TCustomEdit);
procedure SetItemIndex(Value: Integer);
procedure SetKind(Value: TJvLookupAutoCompleteKind);
procedure SetListBox(Value: TCustomListBox);
procedure SetListSearch(Value: Boolean);
procedure SetStrings(Value: TStrings);
function GetActive: Boolean;
procedure SetActive(const Value: Boolean);
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure EvKeyPress(Sender: TObject; var Key: Char); dynamic;
procedure EvDropDown(Sender: TObject); dynamic;
procedure EvValidateStrings(Sender: TObject); dynamic;
procedure EvChange(Sender: TObject); dynamic;
procedure EvValueChange(Sender: TObject); dynamic;
procedure EvItemIndexChange(Sender: TObject); dynamic;
procedure EvValidateItemIndex(Sender: TObject); dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property ItemIndex: Integer read GetItemIndex write SetItemIndex;
published
property Active: Boolean read GetActive write SetActive default True;
property Edit: TCustomEdit read GetEdit write SetEdit;
property ListBox: TCustomListBox read FListBox write SetListBox;
property Strings: TStrings read FStrings write SetStrings;
property Kind: TJvLookupAutoCompleteKind read FKind write SetKind default akListBox;
property ListSearch: Boolean read GetListSearch write SetListSearch default False;
property OnDropDown: TNotifyEvent read FOnDropDown write FOnDropDown;
property OnValidateStrings: TNotifyEvent read FOnValidateStrings write FOnValidateStrings;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnValueChange: TNotifyEvent read FOnValueChange write FOnValueChange;
end;
implementation
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
JvQConsts, JvQJCLUtils;
//=== { TJvControlAutoComplete } =============================================
constructor TJvControlAutoComplete.Create;
begin
inherited Create(nil);
FActive := True;
FMaxFilterTime := 500;
end;
function TJvControlAutoComplete.GetActive: Boolean;
begin
Result := FActive;
end;
procedure TJvControlAutoComplete.SetFilter(const Value: string);
begin
FFilter := Value;
end;
procedure TJvControlAutoComplete.DoValidateItems;
begin
if Assigned(FOnValidateItems) then
FOnValidateItems(Self);
end;
procedure TJvControlAutoComplete.DoChange;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TJvControlAutoComplete.DoDropDown;
begin
if Assigned(FOnDropDown) then
FOnDropDown(Self);
end;
procedure TJvControlAutoComplete.DoValueChange;
begin
if Assigned(FOnValueChange) then
FOnValueChange(Self);
end;
procedure TJvControlAutoComplete.AutoCompleteEvent(Sender: TObject; var Key: Char);
begin
AutoComplete(Key);
end;
procedure TJvControlAutoComplete.AutoComplete(var Key: Char);
var
StartPos, EndPos: Integer;
SaveText, OldText: TCaption;
LastByte: Integer;
LT: Int64;
function HasSelectedText(var StartPos, EndPos: Integer): Boolean;
begin
GetEditSel(StartPos, EndPos);
Result := EndPos > StartPos;
end;
procedure DeleteSelectedText;
var
StartPos, EndPos: Integer;
OldText: string;
begin
OldText := GetText;
GetEditSel(StartPos, EndPos);
Delete(OldText, StartPos + 1, EndPos - StartPos);
SetItemIndex(-1);
SetText(OldText);
SetEditSel(StartPos, StartPos);
end;
function SelectItem(const AnItem: string): Boolean;
var
Idx: Integer;
ValueChange: Boolean;
begin
if AnItem = '' then
begin
Result := False;
SetItemIndex(-1);
DoChange;
Exit;
end;
Idx := FindItemPrefix(-1, AnItem);
Result := (Idx <> -1);
if not Result then
Exit;
ValueChange := Idx <> GetItemIndex;
SetItemIndex(Idx);
if ListSearch then
begin
SetItemIndex(Idx);
FFilter := AnItem;
end
else
begin
SetText(AnItem + Copy(GetItemAt(Idx), Length(AnItem) + 1, MaxInt));
SetEditSel(Length(AnItem), Length(GetText));
end;
if ValueChange then
DoValueChange;
end;
begin
if not Active then
Exit;
if ListSearch then
begin
LT := GetTickCount;
if FLastTime > LT then
LT := $100000000 + LT; // double limit.
if LT - FLastTime >= MaxFilterTime then
FFilter := '';
FLastTime := GetTickCount;
end
else
FFilter := GetText;
case Key of
Esc {VK_ESCAPE}:
Exit;
Tab {VK_TAB}:
begin
DoValidateItems;
DoDropDown;
end;
BackSpace {VK_BACK}:
begin
DoValidateItems;
if HasSelectedText(StartPos, EndPos) then
DeleteSelectedText
else
if not ListSearch and (GetText <> '') then
begin
SaveText := GetText;
LastByte := StartPos;
OldText := Copy(SaveText, 1, LastByte - 1);
SetItemIndex(-1);
SetText(OldText + Copy(SaveText, EndPos + 1, MaxInt));
SetEditSel(LastByte - 1, LastByte - 1);
FFilter := GetText;
end
else
begin
while ByteType(FFilter, Length(FFilter)) = mbTrailByte do
Delete(FFilter, Length(FFilter), 1);
Delete(FFilter, Length(FFilter), 1);
end;
Key := #0;
DoChange;
end;
else
DoValidateItems;
DoDropDown;
if HasSelectedText(StartPos, EndPos) then
SaveText := Copy(FFilter, 1, StartPos) + Key
else
SaveText := FFilter + Key;
if SelectItem(SaveText) then
Key := #0;
end;
end;
//=== { TJvBaseEditListAutoComplete } ========================================
constructor TJvBaseEditListAutoComplete.Create(AEditCtrl: TCustomEdit;
AList: TStrings);
begin
inherited Create;
FList := AList;
EditCtrl := AEditCtrl;
end;
destructor TJvBaseEditListAutoComplete.Destroy;
begin
EditCtrl := nil;
inherited Destroy;
end;
procedure TJvBaseEditListAutoComplete.Notification(AComponent: TComponent;
Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = FEditCtrl) then
begin
FEditCtrl := nil;
SetFilter('');
end;
inherited Notification(AComponent, Operation);
end;
procedure TJvBaseEditListAutoComplete.SetEditCtrl(Value: TCustomEdit);
begin
if Assigned(FEditCtrl) then
FEditCtrl.RemoveFreeNotification(Self);
FEditCtrl := Value;
if Assigned(FEditCtrl) then
FEditCtrl.FreeNotification(Self);
if FEditCtrl <> nil then
SetFilter(FEditCtrl.Text)
else
SetFilter('');
end;
type
TCustomEditAccess = class(TCustomEdit);
function TJvBaseEditListAutoComplete.GetText: TCaption;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -