Can anybody give me some simple code that would give me the ability to search a simple string in a memo and have it highlighted in the memo after being found?
Asked
Active
Viewed 9,374 times
2 Answers
11
This search allows for document wrap, case (in)sensitive search and searching from cursor position.
type
TSearchOption = (soIgnoreCase, soFromStart, soWrap);
TSearchOptions = set of TSearchOption;
function SearchText(
Control: TCustomEdit;
Search: string;
SearchOptions: TSearchOptions): Boolean;
var
Text: string;
Index: Integer;
begin
if soIgnoreCase in SearchOptions then
begin
Search := UpperCase(Search);
Text := UpperCase(Control.Text);
end
else
Text := Control.Text;
Index := 0;
if not (soFromStart in SearchOptions) then
Index := PosEx(Search, Text,
Control.SelStart + Control.SelLength + 1);
if (Index = 0) and
((soFromStart in SearchOptions) or
(soWrap in SearchOptions)) then
Index := PosEx(Search, Text, 1);
Result := Index > 0;
if Result then
begin
Control.SelStart := Index - 1;
Control.SelLength := Length(Search);
end;
end;
You can set HideSelection = False on the memo to show the selection even if the memo isn't focussed.
Use like this:
SearchText(Memo1, Edit1.Text, []);
Allows searching edits as well.

GolezTrol
- 114,394
- 18
- 182
- 210
-
Using UpperCase might not give you the desired results, e.g. in French, the upper case characters cannot not have an accent while lower case characters can have one (that's different from Canadian French I think, where upper case characters can also be accented). So, in this case using LowerCase would give better results. – dummzeuch Nov 20 '10 at 14:40
-
Well, the accented letter and the unaccented letter are two different letters, aren't they? A french word, when converted to UpperCase will show like PRIVé, in lowercase it would be privé. On the other hand, the uppercase letter É isn't converted to é either, so I don't see how that will affect the search results. Though I must admit I'm testing this in Delphi 7. If unicode or the possible use of locale settings in your Delphi yields in better results when using LowerCase, please do. – GolezTrol Nov 20 '10 at 23:21
-
2GolezTrol: Thanks for the HideSelection tip! – RobertFrank Nov 21 '10 at 21:30
3
function TForm1.FindText( const aPatternToFind: String):Boolean;
var
p: Integer;
begin
p := pos(aPatternToFind, Memo1.Text);
Result := (p > 0);
if Result then
begin
Memo1.SelStart := p;
Memo1.SelLength := Length(aPatternToFind);
Memo1.SetFocus; // necessary so highlight is visible
end;
end;
This does NOT search across lines if WordWrap is true.

RobertFrank
- 7,332
- 11
- 53
- 99
-
Searching in `TStrings.Text` rather than `TStrings.Strings` is very expensive. 2×N in the fact. – Free Consulting Nov 23 '10 at 10:49
-
@user205376 - Why do you say that? TStrings.Text is a single string on which I'd think pos() would be fast. Searching, as you suggest, TStrings.Strings would involve subscripts to access each string. That, IMO, opinion, would be slower and provide no additional functionality that the pos() doesn't. (And, it would require some tricky code to highlight the found pattern) Why do you think not? – RobertFrank Nov 25 '10 at 18:27
-
A bit late to the game, but for the above, it depends on the implementation. After all TStrings is abstract. Memo.Lines.Text (= TMemoStrings.Text) gets the text of the memo using a single API call, while a TStringList stores separate string and TStringList.Text combines them into a single string on each request (which is often still faster than calling the API, btw). The answer uses Memo1.Text which I think bypasses any TStrings descendant and directly calls some GetText api on the memo's handle. – GolezTrol Aug 21 '17 at 07:40