maxfax
maxfax

Reputation: 4305

Delphi: Find Dialog & String Grid

Is there a way to do a text search in a string grid using a find dialog? I need to find a text and highlight it's background as usually when a text is found.

Thanks!

Upvotes: 1

Views: 5308

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 108963

Like this:

procedure TForm1.FormClick(Sender: TObject);
begin
  FindDialog1.Execute(Handle)
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FindDialog1.Options := [frDown, frHideWholeWord, frHideUpDown];
end;

procedure TForm1.FindDialog1Find(Sender: TObject);
var
  CurX, CurY, GridWidth, GridHeight: integer;
  X, Y: integer;
  TargetText: string;
  CellText: string;
  i: integer;
  GridRect: TGridRect;
begin
  CurX := StringGrid1.Selection.Left + 1;
  CurY := StringGrid1.Selection.Top;
  GridWidth := StringGrid1.ColCount;
  GridHeight := StringGrid1.RowCount;
  Y := CurY;
  X := CurX;
  if frMatchCase in FindDialog1.Options then
    TargetText := FindDialog1.FindText
  else
    TargetText := AnsiLowerCase(FindDialog1.FindText);
  while Y < GridHeight do
  begin
    while X < GridWidth do
    begin
      if frMatchCase in FindDialog1.Options then
        CellText := StringGrid1.Cells[X, Y]
      else
        CellText := AnsiLowerCase(StringGrid1.Cells[X, Y]);
      i := Pos(TargetText, CellText) ;
      if i > 0 then
      begin
        GridRect.Left := X;
        GridRect.Right := X;
        GridRect.Top := Y;
        GridRect.Bottom := Y;
        StringGrid1.Selection := GridRect;
        Exit;
      end;
      inc(X);
    end;
    inc(Y);
    X := StringGrid1.FixedCols;
  end;
end;

This code can easily be extended to support searching backwards ('up'), and you might also want to implement the 'match whole word' feature.

Perhaps you want to select only the matched text, and not the entire cell? Then do

  if i > 0 then
  begin
    GridRect.Left := X;
    GridRect.Right := X;
    GridRect.Top := Y;
    GridRect.Bottom := Y;
    StringGrid1.Selection := GridRect;
    GetParentForm(StringGrid1).SetFocus;
    StringGrid1.SetFocus;
    StringGrid1.EditorMode := true;
    TCustomEdit(StringGrid1.Components[0]).SelStart := i - 1;
    TCustomEdit(StringGrid1.Components[0]).SelLength := length(TargetText);
    Exit;
  end;

instead. But this will steal the focus from the find dialog, and so the user will not be able to press Return to select the next match, which might be annoying.

Upvotes: 8

Related Questions