实现编辑控件的增量搜索

实现编辑控件的增量搜索

LinZhenqun

2007-10-20

前言

增量搜索(又叫渐进搜索)是我比较喜欢的一种搜索方式,这种一边输入一边搜索的模式常常能更快的找到关键字,特别是在关键字记得不全的时候。大部分代码编辑器都提供了增量搜索的功能,比如DelphiVS。在Delphi,我用得最多的快捷键几乎就是Ctrl+E了。

这几天突然心血来潮,研究了一下增量搜索的原理,成果就是这篇文章,这大概不是最好的实现,不过从搜索速度和结果来看,基本已经满足要求了,这一点从大文件(比如Windows.pas)的测试可以证实。

基本原理就是每输入一个字符就从前一个匹配的位置起搜索关键字,得到的匹配块压进一个栈中。在回退的时候从栈中弹出一个匹配块,然后定位到这个匹配块所指的位置。

更加详细的实现请看下面的代码。

类结构设计

在实现之前,我认为一定有更快的方法,因此必须设计一个更具扩展性的类结构,如下图所示:

IIncreSearch定义了增量搜索的规范,任何增量搜索的类都可以实现该接口。TIncreSearch是一个默认的实现,即上面所说的用栈结构来保存匹配块的方法。注意这里的搜索类并没有与任何控件界面关联,它是一个纯粹的类。

TIncreSearchHandler用于处理支持增量搜索的控件的一些消息,比如字符消息,搜索结束消息;同时它使用IncreSearch来实现控件的增量搜索。

TEdtIncreSearchHandler实现了编辑类控件的增量搜索,关联的控件必须是TCustomEdit类型的。

代码

下面是代码,代码是设计的最佳说明:

{**********************************************************}
{摘要:编辑控件增量搜索实现}
{}
{作者:LinZhenqun}
{日期:2007-10-11}
{邮件:linzhenqun@gmail.net}
{**********************************************************}

unitIncreSearch;

(*******************************************************************************
说明:
1、本单元实现了一个编辑控件的增量搜索。
2IIncreSearch指定增量搜索的规范,任何增量搜索类都应该实现该接口;
3TIncreSearchIIncreSearch的一个默认实现,主要是用栈来保存搜索到的匹配块。
4TInsreSearchHandler为搜索处理器的抽象类,它使用IIncreSearch来实现增量搜索,
同时处理增量搜索的操作逻辑。
5TEditInsreSearchHandler为编辑控件的搜索处理器,与之关联的控件必须是TCustomEdit
类型的控件。

用法:
1、实例化一个处理器,比如TEditInsreSearchHandler,并在构造函数中传进将被搜索
的控件。
2、调用StarteSearch开始增量搜索。
3、调用Searching确定增量搜索是否已经结束。

扩展:
1、增量搜索类:TIncreSearch只是一个默认的搜索实现类,这不是一个最快速的类,
如果你知道如何更快速的实现增量搜索,请实现IIncreSearch接口,并在处理器
的构造函数中传进这个类,比如:
TSomeInsreSearchHandler.Create(TSomeControl,YourIncreSearch);
处理器面对的是搜索接口,因此要特别注意其生命周期的管理。
2、搜索处理器:TEditInsreSearchHandler只能处理TCustomEdit的编辑控件,对于一
些不是从TCustomEdit继承的控件,则必须写另外的处理器。
实现很简单,继承TInsreSearchHandler,并且必须覆盖GetSearchStrGetSearchStart
SetMatchBlock三个抽象方法,提供搜索必需的信息。
如想提供更多的扩展,可以覆盖TInsreSearchHandler其他的虚方法。

******************************************************************************)

interface

uses
Classes,Messages,Controls,Contnrs;

type
{匹配的块}
PMatchBlock=^TMatchBlock;
TMatchBlock=record
Start:Integer;
Len:Integer;
end;

{增量搜索接口}
IIncreSearch=interface
['{A8037752-ED93-49F6-915C-6D8E82ADD631}']
(*开始搜索*)
procedureStartSearch(constSearchStr:string;Start:Integer=0;MaxKey:Word=80);
(*结束搜索*)
procedureEndSearch;
(*增加一个字符*)
functionIncreaseChar(C:Char):PMatchBlock;
(*减少一个字符*)
functionDecreaseChar:PMatchBlock;
(*是否正在搜索*)
functionGetSearching:Boolean;
propertySearching:BooleanreadGetSearching;
end;

{增量搜索的默认实现:利用栈来保存匹配块}
TIncreSearch=class(TInterfacedObject,IIncreSearch)
private
FSearching:Boolean;
FKeyIndex:Integer;
FStart:Integer;
FSearchKey:string;
FSearchStr:string;
FMatchBlockList:TStack;
protected
procedureClearMatchBlockList;
public
procedureStartSearch(constSearchStr:string;Start:Integer=0;MaxKey:Word=80);
procedureEndSearch;
functionIncreaseChar(C:Char):PMatchBlock;
functionDecreaseChar:PMatchBlock;
functionGetSearching:Boolean;
propertySearching:BooleanreadGetSearching;
constructorCreate;
destructorDestroy;override;
end;

{增量搜索处理器,抽象类}
TIncreSearchHandler=class
private
FIncreSearch:IIncreSearch;
protected
FCtrl:TControl;
FOldCtrlWndProc:TWndMethod;
procedureHookWndProc;
procedureUnHookWndProc;
(*控件处理过程,处理增量搜索的字符*)
procedureCtrlWndProc(varMessage:TMessage);virtual;
(*导致增量搜索结束的消息*)
functionIsEndSearchMsg(Message:TMessage):Boolean;virtual;
(*取得等搜索的字符串,必须由子类给出*)
functionGetSearchStr:string;virtual;abstract;
(*取得搜索的起始位置,必须由子类给出*)
functionGetSearchStart:Integer;virtual;abstract;
(*返回搜索关键字的最大长度*)
functionGetMaxKey:Integer;virtual;
(*设置搜到的匹配块,必须由子类实现*)
procedureSetMatchBlock(MatchBlock:PMatchBlock);virtual;abstract;
(*开始搜索,子类作额外处理*)
procedureDoEndSearch;virtual;
(*结束搜索,子类作额外处理*)
procedureDoStartSearch;virtual;
public
procedureStarteSearch;
procedureEndSearch;
functionSearching:Boolean;
propertyCtrl:TControlreadFCtrl;
constructorCreate(ACtrl:TControl;IncreSearch:IIncreSearch=nil);virtual;
destructorDestroy;override;
end;

{编辑控件增量搜索处理器,编辑控件必须从TCustomEdit继承}
TEdtIncreSearchHandler=class(TIncreSearchHandler)
protected
functionGetSearchStr:string;override;
procedureSetMatchBlock(MatchBlock:PMatchBlock);override;
functionGetSearchStart:Integer;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值