Search code examples
delphitextfindhighlightingtstringgrid

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!


Solution

  • 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.