unit UFindText;

interface

uses
  Windows, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Edit1: TEdit;
    Label1: TLabel;
    Edit2: TEdit;
    Label2: TLabel;
    BFind: TButton;
    BElse: TButton;
    GroupBox1: TGroupBox;
    CBCase: TCheckBox;
    CBWord: TCheckBox;
    CBReplace: TCheckBox;
    procedure BFindClick(Sender: TObject);
    procedure BElseClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Messages, RichEdit;

var R: FINDTEXT;   // запись, хранящая диапазон и строку поиска
    Rres: CHARRANGE; // запись с позициями выделяемого текста
    s: string;
    fuFlags: longint; // флаги поиска

procedure TForm1.BFindClick(Sender: TObject);
begin
 if RichEdit1.SelLength > 0
 then begin
// диапазон поиска - выделенный текст
  R.chrg.cpMin := RichEdit1.SelStart;
  R.chrg.cpMax := RichEdit1.SelStart + RichEdit1.SelLength;
 end
 else begin
// диапазон поиска - весь текст
  R.chrg.cpMin := 0;
  R.chrg.cpMax := Length(RichEdit1.Text);
 end;
 s := Edit1.Text;
 R.lpstrText := PChar(s);
// установка флагов поиска
 fuFlags := 0;
 if CBCase.Checked then fuFlags := FT_MATCHCASE;
 if CBWord.Checked then fuFlags := fuFlags or FT_WHOLEWORD;
// уход на поиск
 BElseClick(Sender);
end;

procedure TForm1.BElseClick(Sender: TObject);
// изменение сообщения EM_SCROLLCARET
const EM_SCROLLCARET = $00B7;
begin
// индекс начала найденного текста
 Rres.cpMin := RichEdit1.Perform(EM_FINDTEXT, fuFlags,
                                 Longint(@R));
 if Rres.cpMin = -1
 then ShowMessage('Текст "' + s + '" не найден')
 else begin
  Rres.cpMax := Rres.cpMin + Length(Edit1.Text);
// выделение найденного текста
  RichEdit1.Perform(EM_EXSETSEL, 0, Longint(@Rres));
  if CBReplace.Checked
   then begin
// замена текста
    RichEdit1.Perform(EM_REPLACESEL, 1,
                      Longint(PChar(Edit2.Text)));
// коррекция выделения
    Rres.cpMax := Rres.cpMin + Length(Edit2.Text);
    RichEdit1.Perform(EM_EXSETSEL, 0, Longint(@Rres));
    R.chrg.cpMax := R.chrg.cpMax + Length(Edit2.Text) -
                    Length(Edit1.Text);
   end;
  R.chrg.cpMin := Rres.cpMax;
 end;
// прокрутка текста, чтобы видеть выделение
 RichEdit1.Perform(EM_SCROLLCARET,0,0);
 RichEdit1.SetFocus;
end;

end.
