G
gencheng
Unregistered / Unconfirmed
GUEST, unregistred user!
[原创]让RichEdit支持中文搜索、向上查找、区分大小写!(花费一个多星期的成果)!
RichEdit组件本身为文本搜索提供了FindText()方法,但FindText()方法有一个最大的缺点是不支持中文查找,如果在要搜索的字符串中含有'中文',哪是无论如何也搜不到的,英文则没有任何问题。并且它只提供了向下查找,不只持向上查找。具体原因你看一下VCL源码就知道了。
如果没有一个好的中文搜索,哪么查找,替换功能就无法实现(事实也确实如此)。只支持英文搜索有什么用呢?大家平时主要看的用的都是中文。如果不实现中文搜索,感觉RichEdit就像'鸡肋',甚至我感觉RichEdit只是Borland制造的一个半成品!
解决方法:
本来想直接试改造FindText()方法,但发现要改的地方太多了,有些要改的地方甚至在TWinControl,TControl中,最后才想到用这种思路要实现付出的代价太大,而且效果也不会太好(有可能做出的东西会有BUG或者兼容性差)。
换一种思路解决问题就简单多了,在RichEdit中保留FindText()方法,新增加一个FindTextW()新方法,创建一个新的RichEdit组件--TRichEditW,完整代码如下:
Unit RichEditW;
Interface
Uses
SysUtils, Classes, Controls, StdCtrls, ComCtrls, RichEdit, Dialogs, StrUtils;
Type
TrichEditW = Class(TRichEdit)
Private
{ Private declarations }
Protected
{ Protected declarations }
Public
Function FindTextW(SearchStr: String; Options: TFindOptions): Integer;
Published
{ Published declarations }
End;
Implementation
{ TrichEditW }
Function TrichEditW.FindTextW(SearchStr: String; Options: TFindOptions): Integer;
Var
FoundAt: Integer;
LastFoundAt: Integer;
SearchStrLen: Integer;
AllText: String;
Begin //"查找下一个" 算法
Result := -1;
FoundAt := 0;
If frDown In Options Then //"向下" 查找,找出搜索范围
AllText := System.Copy(Text, SelStart + SelLength + 1, Length(Text))
Else //"向上" 查找,找出搜索范围
AllText := System.Copy(Text, 1, SelStart);
If Not (frMatchCase In Options) Then //非大小写敏感
Begin
AllText := UpperCase(AllText);
SearchStr := UpperCase(SearchStr);
End;
If frDown In Options Then //执行"向下查找"
Begin
FoundAt := Pos(SearchStr, AllText);
If FoundAt = 0 Then
Exit;
//定位光标到指定的字符串
FoundAt := SelStart + SelLength + FoundAt - 1;
End;
If Not (frDown In Options) Then //执行"向上查找"
Begin
SearchStrLen := Length(SearchStr);
FoundAt := Pos(SearchStr, AllText);
If FoundAt = 0 Then //整个部分没找到
Exit
Else //至少找至一个相符的字串
Begin
LastFoundAt := FoundAt; //保存搜到的"第1个字串"位置
Repeat
FoundAt := Posex(SearchStr, AllText, FoundAt + SearchStrLen);
If FoundAt <> 0 Then
LastFoundAt := FoundAt;
Until FoundAt = 0;
FoundAt := LastFoundAt - 1;
End;
End;
Result := FoundAt;
End;
End.
好了,这下用这个新的TRichEditW完全可以代替原来的RichEdit组件,在需要在文本中查询的时候,用新的FindTextW()代替原来的FindText()方法:对于英文,中文查询完全没有问题,并且支持向上,向下,区分大小写(英文)功能。
当然,原来的FindText()也还保留着,对于英文字符的向下搜索应该也是很好的。
上面代码是我在D7,Win2000下做的。Xp下测试也没有问题。欢迎大家继续试用,讨论这个组件。。。
RichEdit组件本身为文本搜索提供了FindText()方法,但FindText()方法有一个最大的缺点是不支持中文查找,如果在要搜索的字符串中含有'中文',哪是无论如何也搜不到的,英文则没有任何问题。并且它只提供了向下查找,不只持向上查找。具体原因你看一下VCL源码就知道了。
如果没有一个好的中文搜索,哪么查找,替换功能就无法实现(事实也确实如此)。只支持英文搜索有什么用呢?大家平时主要看的用的都是中文。如果不实现中文搜索,感觉RichEdit就像'鸡肋',甚至我感觉RichEdit只是Borland制造的一个半成品!
解决方法:
本来想直接试改造FindText()方法,但发现要改的地方太多了,有些要改的地方甚至在TWinControl,TControl中,最后才想到用这种思路要实现付出的代价太大,而且效果也不会太好(有可能做出的东西会有BUG或者兼容性差)。
换一种思路解决问题就简单多了,在RichEdit中保留FindText()方法,新增加一个FindTextW()新方法,创建一个新的RichEdit组件--TRichEditW,完整代码如下:
Unit RichEditW;
Interface
Uses
SysUtils, Classes, Controls, StdCtrls, ComCtrls, RichEdit, Dialogs, StrUtils;
Type
TrichEditW = Class(TRichEdit)
Private
{ Private declarations }
Protected
{ Protected declarations }
Public
Function FindTextW(SearchStr: String; Options: TFindOptions): Integer;
Published
{ Published declarations }
End;
Implementation
{ TrichEditW }
Function TrichEditW.FindTextW(SearchStr: String; Options: TFindOptions): Integer;
Var
FoundAt: Integer;
LastFoundAt: Integer;
SearchStrLen: Integer;
AllText: String;
Begin //"查找下一个" 算法
Result := -1;
FoundAt := 0;
If frDown In Options Then //"向下" 查找,找出搜索范围
AllText := System.Copy(Text, SelStart + SelLength + 1, Length(Text))
Else //"向上" 查找,找出搜索范围
AllText := System.Copy(Text, 1, SelStart);
If Not (frMatchCase In Options) Then //非大小写敏感
Begin
AllText := UpperCase(AllText);
SearchStr := UpperCase(SearchStr);
End;
If frDown In Options Then //执行"向下查找"
Begin
FoundAt := Pos(SearchStr, AllText);
If FoundAt = 0 Then
Exit;
//定位光标到指定的字符串
FoundAt := SelStart + SelLength + FoundAt - 1;
End;
If Not (frDown In Options) Then //执行"向上查找"
Begin
SearchStrLen := Length(SearchStr);
FoundAt := Pos(SearchStr, AllText);
If FoundAt = 0 Then //整个部分没找到
Exit
Else //至少找至一个相符的字串
Begin
LastFoundAt := FoundAt; //保存搜到的"第1个字串"位置
Repeat
FoundAt := Posex(SearchStr, AllText, FoundAt + SearchStrLen);
If FoundAt <> 0 Then
LastFoundAt := FoundAt;
Until FoundAt = 0;
FoundAt := LastFoundAt - 1;
End;
End;
Result := FoundAt;
End;
End.
好了,这下用这个新的TRichEditW完全可以代替原来的RichEdit组件,在需要在文本中查询的时候,用新的FindTextW()代替原来的FindText()方法:对于英文,中文查询完全没有问题,并且支持向上,向下,区分大小写(英文)功能。
当然,原来的FindText()也还保留着,对于英文字符的向下搜索应该也是很好的。
上面代码是我在D7,Win2000下做的。Xp下测试也没有问题。欢迎大家继续试用,讨论这个组件。。。