如何在备忘录中查找并 select 特定单词的每次出现?
How to find and select every occurences of specific word in Memo?
我正在制作一个应用程序来替换两种非常相似的语言的不同单词。按时间字数大概会达到至少10.000+。文字上没有太大的区别,几乎是同一种语言,但是却存在差异。
所以,我设法以足够快的速度替换了 Memo 中的单词,但我不知道如何 select Memo 中所有替换的单词,以便可以看到哪些单词被替换了。这可能吗?
单词是这样替换的:
procedure TForm1.TranslateExecute(Sender: TObject);
var i: integer;
S, OldPattern, NewPattern: string;
begin
S:= Memo1.Lines.Text;
for i := 0 to (StrListV.Count - 1) do {StrListV is created earlier, contains words that should be replaced}
begin
OldPattern:= StrListV.Strings[i];
NewPattern:= StrListV1.Strings[i]; {StrListV1 contains new words}
S:= FastStringReplace(S, OldPattern, NewPattern,[rfReplaceAll]);
end;
Memo1.BeginUpdate;
Memo1.Clear;
Memo1.Lines.Text:= S;
Memo1.EndUpdate;
end;
TMemo
或 TRichEdit
都不支持多个 selection,因此您实际上无法突出显示已替换的单词。但是对于 TRichEdit
,你可以做的是改变你替换的单词的 foreground/background 颜色。
TRichEdit
有一个 FindText()
方法(包装 EM_FINDTEXT
消息),returns 是搜索字符串的索引。在循环中调用它,或者每个找到的单词都可以 select 它,设置它的颜色,然后用新文本替换它。重复直到 FindText()
找不到更多匹配项。
尝试这样的事情:
uses
RichEdit, CommDlg;
procedure TForm1.TranslateExecute(Sender: TObject);
var
I, Pos: Integer;
EventMask: LRESULT;
OldPattern, NewPattern: string;
Find: RichEdit.FINDTEXT;
Rng: RichEdit.CHARRANGE;
Fmt: RichEdit.CHARFORMAT2;
begin
EventMask := SendMessage(RichEdit1.Handle, EM_SETEVENTMASK, 0, 0);
RichEdit1.Lines.BeginUpdate;
try
for I := 0 to StrListV.Count - 1 do
begin
OldPattern := StrListV.Strings[I];
NewPattern := StrListV1.Strings[I];
Pos := 0;
repeat
Find.chrg.cpMin := Pos;
Find.chrg.cpMax := -1;
Find.lpstrText := PChar(OldPattern);
Pos := SendMessage(RichEdit1.Handle, EM_FINDTEXT, FR_DOWN or FR_WHOLEWORD, LPARAM(@Find));
if Pos = -1 then Break;
Rng.cpMin := Pos;
Rng.cpMax := Pos + Length(OldPattern);
ZeroMemory(@Fmt, SizeOf(Fmt));
Fmt.cbSize := SizeOf(Fmt);
Fmt.dwMask := CFM_COLOR or CFM_BACKCOLOR;
Fmt.crTextColor := ColorToRGB(clHighlightText);
Fmt.crBackColor := ColorToRGB(clHighlight);
SendMessage(RichEdit1.Handle, EM_EXSETSEL, 0, LPARAM(@Rng));
SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
SendMessage(RichEdit1.Handle, EM_REPLACESEL, 0, LPARAM(PChar(NewPattern)));
Inc(Pos, Length(NewPattern));
until False;
end;
finally
RichEdit1.Lines.EndUpdate;
SendMessage(RichEdit1.Handle, EM_SETEVENTMASK, 0, EventMask);
end;
end;
我正在制作一个应用程序来替换两种非常相似的语言的不同单词。按时间字数大概会达到至少10.000+。文字上没有太大的区别,几乎是同一种语言,但是却存在差异。
所以,我设法以足够快的速度替换了 Memo 中的单词,但我不知道如何 select Memo 中所有替换的单词,以便可以看到哪些单词被替换了。这可能吗?
单词是这样替换的:
procedure TForm1.TranslateExecute(Sender: TObject);
var i: integer;
S, OldPattern, NewPattern: string;
begin
S:= Memo1.Lines.Text;
for i := 0 to (StrListV.Count - 1) do {StrListV is created earlier, contains words that should be replaced}
begin
OldPattern:= StrListV.Strings[i];
NewPattern:= StrListV1.Strings[i]; {StrListV1 contains new words}
S:= FastStringReplace(S, OldPattern, NewPattern,[rfReplaceAll]);
end;
Memo1.BeginUpdate;
Memo1.Clear;
Memo1.Lines.Text:= S;
Memo1.EndUpdate;
end;
TMemo
或 TRichEdit
都不支持多个 selection,因此您实际上无法突出显示已替换的单词。但是对于 TRichEdit
,你可以做的是改变你替换的单词的 foreground/background 颜色。
TRichEdit
有一个 FindText()
方法(包装 EM_FINDTEXT
消息),returns 是搜索字符串的索引。在循环中调用它,或者每个找到的单词都可以 select 它,设置它的颜色,然后用新文本替换它。重复直到 FindText()
找不到更多匹配项。
尝试这样的事情:
uses
RichEdit, CommDlg;
procedure TForm1.TranslateExecute(Sender: TObject);
var
I, Pos: Integer;
EventMask: LRESULT;
OldPattern, NewPattern: string;
Find: RichEdit.FINDTEXT;
Rng: RichEdit.CHARRANGE;
Fmt: RichEdit.CHARFORMAT2;
begin
EventMask := SendMessage(RichEdit1.Handle, EM_SETEVENTMASK, 0, 0);
RichEdit1.Lines.BeginUpdate;
try
for I := 0 to StrListV.Count - 1 do
begin
OldPattern := StrListV.Strings[I];
NewPattern := StrListV1.Strings[I];
Pos := 0;
repeat
Find.chrg.cpMin := Pos;
Find.chrg.cpMax := -1;
Find.lpstrText := PChar(OldPattern);
Pos := SendMessage(RichEdit1.Handle, EM_FINDTEXT, FR_DOWN or FR_WHOLEWORD, LPARAM(@Find));
if Pos = -1 then Break;
Rng.cpMin := Pos;
Rng.cpMax := Pos + Length(OldPattern);
ZeroMemory(@Fmt, SizeOf(Fmt));
Fmt.cbSize := SizeOf(Fmt);
Fmt.dwMask := CFM_COLOR or CFM_BACKCOLOR;
Fmt.crTextColor := ColorToRGB(clHighlightText);
Fmt.crBackColor := ColorToRGB(clHighlight);
SendMessage(RichEdit1.Handle, EM_EXSETSEL, 0, LPARAM(@Rng));
SendMessage(RichEdit1.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));
SendMessage(RichEdit1.Handle, EM_REPLACESEL, 0, LPARAM(PChar(NewPattern)));
Inc(Pos, Length(NewPattern));
until False;
end;
finally
RichEdit1.Lines.EndUpdate;
SendMessage(RichEdit1.Handle, EM_SETEVENTMASK, 0, EventMask);
end;
end;