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 ...
随机推荐
- 《深入理解Java虚拟机》笔记--第二章、Java内存区域与内存溢出异常
Java程序员把内存的控制权交给了Java虚拟机.在Java虚拟机内存管理机制的帮助下,程序员不再需要为每一个new操作写对应的delete/free代码,而且不容易出现内存泄露和溢出. 虚拟机在执行 ...
- javascript初步了解
0.1 <script> 和 </script> 会告诉 JavaScript 在何处开始和结束. <script> 和 </script> 之间的 ...
- 对cgic的理解——name选项
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cgic.h" ...
- python discover 函数介绍
discover(start_dir,pattern='test*.py',top_level_dir=None)找到指定目录下所有测试模块,并可递归查到子目录下的测试木块,只有匹配到的文件名才会被加 ...
- Python+Selenium 自动化实现实例-获取测试对象的Css属性
#coding:utf-8 '''获取测试对象的css属性场景 当你的测试用例纠结细枝末节的时候,你就需要通过判断元素的css属性来验证你的操作是否达到了预期的效果.比如你可以通过判断页面上的标题字号 ...
- Spring Boot Admin Quick Start
Quick Start 1. Spring Boot Admin是干什么的? 用来监控Spring Boot项目,可以通过Spring Boot Admin Client(via Http) 或者 使 ...
- csu 1548(三分)
1548: Design road Time Limit: 2 Sec Memory Limit: 256 MBSubmit: 383 Solved: 200[Submit][Status][We ...
- First Missing Positive——数学类
转:http://blog.csdn.net/nanjunxiao/article/details/12973173 Given an unsorted integer array, find the ...
- Flyweight模式(亨元模式)
这应该算是最好理解的一个设计模式了吧·················· 面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个 ...
- 编译PHP并与Ngnix整合
nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端. nginx一般是把请求发fastcgi管理进程处理,fascgi管 ...