我们正在与XE7合作。我们正在尝试构建一个搜索功能并将其替换为一个TRichEdit。
我们希望它能像在Delphi编译器中一样工作。我们显示我们自己的搜索和替换对话框,我们没有使用Delphi替换对话框。
我们显示对话框,当用户单击“替换”按钮时,对话框将关闭,对于找到的每个实例,我们希望弹出一个消息对话框,询问用户是否要替换该事件。
当我们这样做时,用户无法看到所选择的内容,如果他们在消息对话框上单击“是”,则不会替换任何内容。
我们的代码如下:
procedure Tviewform.select_text(fndpos:integer);
begin
setfocus;
asciieditor.selstart:=fndpos;
asciieditor.sellength:=length(vwvars[curviewwin]^.finddata);
end;
procedure Tviewform.search_and_replace;
var position,endpos,fndans,cont:integer; foptions:tsearchtypes; msgques,stopall:word;
begin
with asciieditor do
begin
endpos:=length(asciieditor.text)-vwvars[curviewwin]^.sstartpos;
foptions:=[];
stopall:=0;
cont:=0;
if findinfo.onbut.checked then foptions:=foptions+[stMatchCase];
lines.beginupdate;
fndans:=findtext(vwvars[curviewwin]^.finddata,vwvars[curviewwin]^.sstartpos,endpos,foptions);
while (fndans<>-1) and (stopall=0) do
begin
select_text(fndans);
msgques:=mainform.silang1.messagedlg('Replace with '+vwvars[curviewwin]^.replace+'?.',mtinformation,[mbyes,mbno,mbcancel],0);
if msgques=mryes then
begin
asciieditor.clearselection;
seltext:=vwvars[curviewwin]^.replace;
end else
begin
if msgques=mrcancel then
begin
cont:=0;
stopall:=1;
end else cont:=1;
end;
asciieditor.Repaint;
if cont=1 then
begin
inc(vwvars[curviewwin]^.sstartpos,length(vwvars[curviewwin]^.finddata));
endpos:=length(asciieditor.text)-vwvars[curviewwin]^.sstartpos;
fndans:=findtext(vwvars[curviewwin]^.finddata,vwvars[curviewwin]^.sstartpos,endpos,foptions);
end;
end;
lines.endupdate;
end;
end;发布于 2022-07-08 01:50:47
我在您的代码中看到了一些问题:
select_text()和MessageDlg()时,将输入焦点从TRichEdit移开,因此确保TRichEdit.HideSelection设置为False (默认情况下为True ),以便实际查看所选内容。您正在调用的Repaint().上的
BeginUpdate()设置TRichEdit.SelText.之前不需要调用TRichEdit.ClearSelection()的
vwvars[curviewwin]^.sstartpos时,需要将其重置为fndAns (当前选择的位置)加上vwvars[curviewwin]^.replace的长度(新文本),而不是vwvars[curviewwin]^.finddata (旧文本)的长度。您不会将它移到新文本之外,因此您正在一遍又一遍地搜索旧文本。MessageDlg()中选择No,则不更新vwvars[curviewwin]^.sstartpos以通过用户不想替换的文本。endpos时,length(asciieditor.text)可以改为asciieditor.gettextlen(),以提高效率。但更重要的是,您根本不应该从vwvars[curviewwin]^.sstartpos中减去endpos。通过这样做,您将从搜索中跳过越来越多的TRichEdit末尾的文本,并进行每一次替换。事实上,您应该只使用asciieditor的当前文本长度作为每次搜索的结束位置,因此您实际上根本不需要endpos。。
根据您的
MessageDlg()之前向TRichEdit发送EM_SCROLLCARET消息,以防匹配的文本离开屏幕。说到这里,尝试更像这样的东西:
procedure Tviewform.search_and_replace;
var
fndAns: Integer;
fOptions: TSearchTypes;
msgQues: Word;
procedure select_text;
begin
{AsciiEditor.}SetFocus;
AsciiEditor.SelStart := fndAns;
AsciiEditor.SelLength := Length(vwvars[curviewwin]^.finddata);
AsciiEditor.Perform(EM_SCROLLCARET, 0, 0);
AsciiEditor.Update;
end;
begin
fOptions := [];
if FindInfo.OnBut.Checked then Include(fOptions, stMatchCase);
repeat
fndAns := AsciiEditor.FindText(vwvars[curviewwin]^.finddata, vwvars[curviewwin]^.sstartpos, AsciiEditor.GetTextLen, fOptions);
if fndAns = -1 then Break;
select_text;
msgQues := MainForm.SiLang1.MessageDlg('Replace with ' + vwvars[curviewwin]^.replace + '?', mtinformation, [mbYes,mbNo,mbCancel], 0);
if msgQues = mrYes then
begin
AsciiEditor.SelText := vwvars[curviewwin]^.replace;
AsciiEditor.Update;
Inc(fndAns, Length(vwvars[curviewwin]^.replace));
end
else if msgQues = mrNo then
begin
Inc(fndAns, Length(vwvars[curviewwin]^.finddata));
end else
Break;
vwvars[curviewwin]^.sstartpos := fndAns;
until False;
end;https://stackoverflow.com/questions/72905719
复制相似问题