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 ...
随机推荐
- spring-mybatis.xml配置
1.自动扫描 <context:component-scan base-package="com.javen" /> 2.引入配置文件 <bean id=&quo ...
- 使用jolokia api监控ActiveMQ
jolokia api提供了一种通过HTTP访问JMX获得AMQ后台数据的一种方式,即Restful Api #!/usr/bin/env python # -*- coding:utf-8 -*- ...
- linux下查看资源使用情况
//查看占用内存最多的前K的程序ps aux | sort -k4nr | head -K //查看占用CPU最多的前K的程序 ps aux | sort -k3nr | head -K
- 连接数据库:ERROR:The server time zone value '?й???????' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration prop
本打算在maven项目中配置mybatis试试看,想到mybatis如果不是在容器中运行,那么他的事务控制实际上可以使用的是jdbc的提交和回滚,这就要在pom.xml文件中配置mysql-conne ...
- spring mvc整合mybaitis和log4j
在上一篇博客中,我介绍了在mac os上用idea搭建spring mvc的maven工程,但是一个完整的项目肯定需要数据库和日志管理,下面我就介绍下spring mvc整合mybatis和log4j ...
- linux 下vim文件乱码 cat文件正常处理方法
linux 下vim文件乱码 cat文件正常处理方法 服务器支持中文字符集,cat和其他查看文件命令现在正常,vim还是出现了中文乱码问题, 1.查看文件编码格式 vim 文件 :set fileen ...
- LR参数和变量
一.参数: 1. 在LR函数中可以直接使用参数.参数必须在双引号“”中才能应用.大部分情况下,可以直接用参数代替函数中双引号内的数据.如下使用方法: lr_save_string("http ...
- 【leetcode】 21. Merge Two Sorted Lists
题目描述: Merge two sorted linked lists and return it as a new list. The new list should be made by spli ...
- 洛谷P2243 电路维修 [最短路]
题目传送门 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和Jam ...
- Python数据类型-列表(list)增删改查
1.添加元素 添加单个元素:使用append(object)函数可以为列表添加单个元素,参数object为对象:也就是说所有Python的对象都可以添加到列表中. 添加多个元素(合并列表):使用ext ...