Autocomplete TEdit
http://forum.codecall.net/topic/75946-autocomplete-tedit/
Overview
Autocomplete feature really helpful for us speeding up our typing job.
For you who is not familiar with the term autocomplete,
it's when you type partial part of a word and then
you will be presented with a list of possible complete words.
You can just select the correct word from the list,
and that partial word will be automatically completed.
In programming, this feature very helpful to
"remember" class names, routine names, and variable name.
Not only to speed up the typing, autocomplete also very helpful to avoid typo.
In this tutorial I will show you a technique to implement autocomplete
in your Delphi program in order to provide your users the benefits of autocomplete.
I will implement autocomplete in a descendant of TEdit. I name it TAutocompleteEdit.
TAutoCompleteEdit
Behaviors
- Upon typing some chars, TAutocompleteEdit will check the typed word agains a word list. When no match found, do nothing.
- When one or more matches found, TAutocompleteEdit show the matches in a TListBox.We will call this TListBoxWordList.
- User can move between TAutocompleteEdit and WordList using down and up arrow.
- User select a complete word from WordList by highlighting the word and press Enter key.
- After user selected a word, the word will replace whatever content in TAutocompleteEdit.
- If user press Escape in TAutocompleteEdit or in WordList, WordList must dissapear.
- If TAutocompleteEdit lost focus, and the new focus is not in WordList, WordList must dissapear.
- If WordList lost focus, and the new focus is not in TAutocompleteEdit, WordList must dissapear.
- If later user type in another character and no match found, WordList must dissapear.
Key Methods
From the above behaviors, we decided to have the following methods.
- ShowWordList(AWords: TStrings).
This method is responsible to create WordList TListBox when needed,
populate it with words contained in AWords, and
also to patch its events so we can achieve behavior #3, #4, #5, #6, and #8. - HideWordList.
This method is responsible to hide and clean up WordList. - Change.
This is where to respond when the content of TAutocompleteEdit changed.
So this is where we do the checking.
This method actually already exist in TAutocompleteEdit's parent.
So what we are going to do is override it, and introduce our behavior. - DoExit.
This method also already exist in TAutocompleteEdit's parent.
We are going to override it and introduce new behavior, in order to achieve behavior #7. - KeyDown(var Key: Word; Shift: TShiftState).
This method also already exist in TAutocompleteEdit's parent.
We are going to override it to achieve behavior #3 and #6.
Key Methods Implementations
1. ShowWordList(AWords: TStrings).
procedure TAutocompleteEdit.ShowWordList(AWords: TStrings);
begin
if FWordList=nil then
begin
FWordList := TListBox.Create(Self);
FWordList.ParentCtl3D := False;
FWordList.Ctl3D := False;
FWordList.Parent := Self.Parent;
FWordList.TabStop := False;
FWordList.OnExit := HandleWordListLostFocus;
FWordList.OnKeyPress := HandleWordListKeyPress;
FWordList.OnKeyDown := HandleWordListKeyDown;
end; FWordList.Items.Assign(AWords);
if FWordListWidth < then
FWordList.SetBounds(Self.Left, Self.Top + Self.Height, Self.Width, FWordListHeight)
else
FWordList.SetBounds(Self.Left, Self.Top + Self.Height, FWordListWidth, FWordListHeight); FWordList.Show;
end;
2. HideWordList
procedure TAutocompleteEdit.HideWordList;
begin
PostMessage(Self.Handle, MSG_HIDEWORDLIST, , );
end;
Note that in the above method we only post a custom message. The custom message handler in turn will call this private method.
procedure TAutocompleteEdit.HandleHideWordList;
begin
FWordList.Free;
FWordList := nil;
end;
3. Change.
procedure TAutocompleteEdit.Change;
var
S: TStrings;
begin
inherited;
if AutocompleteMan.IsRecognized(Self.Text) then
begin
S := TStringList.Create;
try
if AutocompleteMan.IsRecognized(Self.Text, S) then
ShowWordList(S);
finally
S.Free;
end;
end
else
HideWordList;
end;
4. DoExit.
procedure TAutocompleteEdit.DoExit;
begin
if Assigned(FWordList) and FWordList.Visible and not FWordList.Focused then
HideWordList;
inherited;
end;
5. KeyDown(var Key: Word; Shift: TShiftState).
procedure TAutocompleteEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
if Key=VK_ESCAPE then
HideWordList
else if (Key=VK_DOWN) and Assigned(FWordList) and FWordList.Visible then
begin
FCaretPos := Self.SelStart;
FWordList.SetFocus;
if FWordList.ItemIndex < then
FWordList.ItemIndex := ;
end
else
inherited;
end;
Here is the complete source code of TAutocompleteEdit:
TEdit with Autocomplete.zip 1.84MB 603 downloads.
Feel free to use it or improve it for any kind of use.
Cheers!
unit AutocompleteEdit; interface uses
Windows
, Classes
, Vcl.StdCtrls
, SysUtils
, StrUtils
, Messages
; const
MSG_HIDEWORDLIST = WM_USER + ; type
TAutocompleteEdit=class(TEdit)
private
FWordList: TListBox;
FCaretPos: Integer;
FWordListHeight: Integer;
FWordListWidth: Integer; procedure HandleWordListLostFocus(ASender: TObject);
procedure HandleWordListSelectItem(ASender: TObject);
procedure HandleWordListKeyPress(Sender: TObject; var Key: Char);
procedure HandleWordListKeyDown(ASender: TObject; var Key: Word; Shift: TShiftState);
procedure HandleHideWordList(var AMsg); overload; message MSG_HIDEWORDLIST;
procedure HandleHideWordList; overload;
procedure SetWordListHeight(const Value: Integer);
procedure SetWordListWidth(const Value: Integer); procedure RegainFocus;
protected
procedure ShowWordList(AWords: TStrings);
procedure HideWordList;
procedure Change; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure DoExit; override;
public
constructor Create(AOwner: TComponent); override;
published
property WordListHeight: Integer read FWordListHeight write SetWordListHeight;
property WordListWidth: Integer read FWordListWidth write SetWordListWidth;
end; TAutocompleteMan=class
private
FWords: TStrings;
public
constructor Create;
destructor Destroy; override; function IsRecognized(AWord: string): Boolean; overload;
function IsRecognized(AWord: string; AWordList: TStrings): Boolean; overload; procedure LoadFromFile(const AFilename: string);
procedure AddWord(const AWord: string); property Words: TStrings read FWords;
end; procedure Register; var
AutocompleteMan: TAutocompleteMan; implementation procedure Register;
begin
RegisterComponents('CodeCall', [TAutocompleteEdit]);
end; { TAutocompleteMan } procedure TAutocompleteMan.AddWord(const AWord: string);
begin
FWords.Add(UpperCase(AWord) + '=' + AWord);
end; constructor TAutocompleteMan.Create;
begin
FWords := TStringList.Create;
TStringList(FWords).Duplicates := dupIgnore;
end; destructor TAutocompleteMan.Destroy;
begin
FWords.Free;
inherited;
end; function TAutocompleteMan.IsRecognized(AWord: string): Boolean;
var
i: Integer;
begin
Result := False;
AWord := UpperCase(AWord);
for i := to FWords.Count- do
begin
Result := System.Pos(AWord, FWords.Names[i]) > ;
if Result then
Break;
end;
end; function TAutocompleteMan.IsRecognized(AWord: string;
AWordList: TStrings): Boolean;
var
i: Integer;
begin
Result := False;
AWord := UpperCase(AWord);
AWordList.Clear;
for i := to FWords.Count- do
begin
if System.Pos(AWord, FWords.Names[i]) > then
begin
Result := True;
AWordList.Add(FWords.ValueFromIndex[i]);
end;
end;
end; procedure TAutocompleteMan.LoadFromFile(const AFilename: string);
var
i: Integer;
F: TStrings;
begin
F := TStringList.Create;
try
F.LoadFromFile(AFilename);
for i := to F.Count- do
AddWord(F[i]);
finally
F.Free;
end;
end; { TAutocompleteEdit } procedure TAutocompleteEdit.Change;
var
S: TStrings;
begin
inherited;
if AutocompleteMan.IsRecognized(Self.Text) then
begin
S := TStringList.Create;
try
if AutocompleteMan.IsRecognized(Self.Text, S) then
ShowWordList(S);
finally
S.Free;
end;
end
else
HideWordList;
end; procedure TAutocompleteEdit.HandleHideWordList(var AMsg);
begin
HandleHideWordList;
end; constructor TAutocompleteEdit.Create(AOwner: TComponent);
begin
inherited;
FWordListHeight := ;
end; procedure TAutocompleteEdit.DoExit;
begin
if Assigned(FWordList) and FWordList.Visible and not FWordList.Focused then
HideWordList;
inherited;
end; procedure TAutocompleteEdit.HandleHideWordList;
begin
FWordList.Free;
FWordList := nil;
end; procedure TAutocompleteEdit.HandleWordListKeyDown(ASender: TObject;
var Key: Word; Shift: TShiftState);
begin
if (Key=VK_UP) and (FWordList.ItemIndex=) then
RegainFocus;
end; procedure TAutocompleteEdit.HandleWordListKeyPress(Sender: TObject;
var Key: Char);
begin
case Key of
#: begin
Key := #;
Self.Text := FWordList.Items[FWordList.ItemIndex];
Self.SetFocus;
Self.SelStart := Length(Self.Text);
Self.SelLength := ;
HideWordList;
end;
#: begin
RegainFocus;
HideWordList;
end;
else begin
RegainFocus;
end;
end;
end; procedure TAutocompleteEdit.HandleWordListLostFocus(ASender: TObject);
begin
if not Self.Focused then
HideWordList;
end; procedure TAutocompleteEdit.HandleWordListSelectItem(ASender: TObject);
begin
Self.Text := FWordList.Items[FWordList.ItemIndex];
HideWordList;
end; procedure TAutocompleteEdit.HideWordList;
begin
PostMessage(Self.Handle, MSG_HIDEWORDLIST, , );
end; procedure TAutocompleteEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
if Key=VK_ESCAPE then
HideWordList
else if (Key=VK_DOWN) and Assigned(FWordList) and FWordList.Visible then
begin
FCaretPos := Self.SelStart;
FWordList.SetFocus;
if FWordList.ItemIndex < then
FWordList.ItemIndex := ;
end
else
inherited;
end; procedure TAutocompleteEdit.RegainFocus;
begin
Self.SetFocus;
Self.SelStart := FCaretPos;
Self.SelLength := ;
end; procedure TAutocompleteEdit.SetWordListHeight(const Value: Integer);
begin
if FWordListHeight <> Value then
begin
FWordListHeight := Value;
if Assigned(FWordList) then
FWordList.Height := FWordListHeight;
end;
end; procedure TAutocompleteEdit.SetWordListWidth(const Value: Integer);
begin
if FWordListWidth <> Value then
begin
FWordListWidth := Value;
if Assigned(FWordList) then
begin
if FWordListWidth < then
FWordList.Width := Self.Width
else
FWordList.Width := FWordListWidth;
end;
end;
end; procedure TAutocompleteEdit.ShowWordList(AWords: TStrings);
begin
if FWordList=nil then
begin
FWordList := TListBox.Create(Self);
FWordList.ParentCtl3D := False;
FWordList.Ctl3D := False;
FWordList.Parent := Self.Parent;
FWordList.TabStop := False;
FWordList.OnExit := HandleWordListLostFocus;
FWordList.OnKeyPress := HandleWordListKeyPress;
FWordList.OnKeyDown := HandleWordListKeyDown;
end; FWordList.Items.Assign(AWords);
if FWordListWidth < then
FWordList.SetBounds(Self.Left, Self.Top + Self.Height, Self.Width, FWordListHeight)
else
FWordList.SetBounds(Self.Left, Self.Top + Self.Height, FWordListWidth, FWordListHeight); FWordList.Show;
end; initialization
AutocompleteMan := TAutocompleteMan.Create; finalization
AutocompleteMan.Free;
end.
Autocomplete TEdit的更多相关文章
- autocomplete的使用
autocomplete使用分为本地调用方法和读取远程读取数据源的方法 (1)本地调用方法 <script src="Scripts/jquery-1.4.1.min.js" ...
- 原生js实现autocomplete插件
在实际的项目中,能用别人写好的插件实现相关功能是最好不过,为了节约时间成本,因为有的项目比较紧急,没充分时间让你自己来写,即便写了,你还要花大量时间调试兼容性.但是出于学习的目的,你可以利用闲暇时间, ...
- jQuery ui autocomplete 与easyUI冲突解决办法(重命名ui的autocomplete 和menu部分)
http://jqueryui.com/download/ UI定制只选autocomplete 会自动把依赖的menu模块也加入进来--然而easyUI也有自己的menu,于是就-- 折腾了好久 ...
- AutoComplete
aspx页面 需要引用的文件: <link rel="stylesheet" type="text/css" href="css/jquery. ...
- Bootstrap 中的 Typeahead 组件 -- AutoComplete
Bootstrap 中的 Typeahead 组件就是通常所说的自动完成 AutoComplete,功能很强大,但是,使用上并不太方便.这里我们将介绍一下这个组件的使用. 第一,简单使用 首先,最简单 ...
- Delphi控件之---UpDown以及其与TEdit的配合使用(比如限制TEdit只能输入数字,还有Object Inspector之组件属性的介绍)
最近在开发中使用到了UpDown这个控件,但是因为之前没有使用过,所以很不熟悉,于是就编写了一个简单的demo来学习UpDown以及其结合TEdit的用法. 初步的常用功能的简介 目前(2015.08 ...
- smartComplete——轻量级的autoComplete插件,开源
项目后端觉得autoComplete响应略慢,于是花了两天时间写了这插件,基于jQuery 1.7+,仓库地址 https://github.com/VaJoy/smartComplete ,欢迎各种 ...
- Autocomplete 自动补全(Webform实战篇)
开篇语 因为项目中需要用到一个自动补全的功能,功能描述: 需求一:新增收件人的时候,自动下拉显示出数据库中所有的收件人信息(显示的信息包括:姓名-收件地址-联系方式) 需求二:选中一个值得时候,分别赋 ...
- jQuery AutoComplete在AJAX UpdatePanel环境中PostBack之后无法工作
前些日子,Insus.NET有实现<ASP.NET MVC使用jQuery实现Autocomplete>http://www.cnblogs.com/insus/p/5638895.htm ...
随机推荐
- WebAPI使用Swagger生成接口文档
开发工具:VS2017 版本15.7.1 新建项目,选择空模板,下面只勾选WebAPI 配置Web.config <system.webServer> 节点改为 <system.we ...
- PHP扩展插件 imagick 、PDO_MYSQL 安装
环境准备 echo $LC_ALL echo "export LC_ALL=C" >> /etc/profile source /etc/profile yum ins ...
- mongodb与mysql传统的关系数据库区别
转自:易百教程 MongoDB中的数据具有灵活的模式.文档在同一集合,但它们不需要具有相同的字段或结构集合,集合文档中的公共字段可以包含不同类型的数据. MongoDB中的数据具有灵活的模式.与SQL ...
- Linux 基础——关机重启命令shutdown、reboot等
一.关机重启命令的作用 相信对于接触过电脑的人来说,特别是对于windows系统来说,如果长时间使用不经重启的话会出现一点点卡顿的感觉.但是当重启整个系统后,这点点卡顿的感觉好像又没了,重启后wind ...
- promise应用于ajax
promise应用于ajax,可以在本页打开控制台,复制代码试验 var url = 'https://www.cnblogs.com/mvc/blog/news.aspx?blogApp=dkplu ...
- 强大到无与伦比的Graphviz
图1 hello world 尝试画复杂一些的图: 一直苦苦寻找用于图论的画图软件,偶然在Matrix67的这篇博文里找到. Graphviz使用dot语言,这门不仅语言非常简单易学,而且功能却非常强 ...
- 【58沈剑架构系列】主从DB与cache一致性
本文主要讨论这么几个问题: (1)数据库主从延时为何会导致缓存数据不一致 (2)优化思路与方案 一.需求缘起 上一篇<缓存架构设计细节二三事>中有一个小优化点,在只有主库时,通过“串行化” ...
- lr_start_transaction/lr_end_transaction事物组合
lr_start_transaction/lr_end_transaction事物组合 总结一下: lr_start_transaction与lr_end_transaction 为使用最多的事物创造 ...
- jquery 美化弹出提示 漂亮的Dialog 对话框
三个不同的效果,分别是普通的警告,确认/取消,带一个输入框 本例用了jquery.alertify.js,请到演示页面查看 css文件也请到演示页面查看 JavaScript Code <scr ...
- 转:gcc编译C++程序
转:http://blog.csdn.net/liujiayu2/article/details/49864381 单个源文件生成可执行程序 下面是一个保存在文件 helloworld.cpp 中一个 ...