Foros Club Delphi

Foros Club Delphi (http://www.clubdelphi.com/foros/index.php)
-   Trucos (http://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   Vcl/FMX: Resaltar texto parcialmente (http://www.clubdelphi.com/foros/showthread.php?t=90619)

AgustinOrtu 28-07-2016 05:14:46

Vcl/FMX: Resaltar texto parcialmente
 
Hola a todos

Este truco sirve cuando por ejemplo mostramos datos en un Grid y queremos resaltar parte del texto (color, negrita, etc). Esta muy bueno cuando hacemos una busqueda parcial, y queda resaltado que parte del string es la que coincide con la busqueda.

El efecto buscado seria, si busco Juan que me resalte asi:

Juan
Juan Carlos
Pedro Juan
AlgoJuanOtraCosa

El codigo en realidad es obra de ecfisa, lo interesante es que el algoritmo es aplicable facilmente a casi cualquier clase, porque todo se basa en codigo RTL para manipulacion de strings, y luego el pintado es usando TCanvas. Es cierto que hay algunas pequeñas diferencias entre el manejo de Canvas Vcl y el de FMX

Si yo no he entendido mal, lo que hace Daniel es ir dibujando con el canvas de a "trocitos" el string, dividiendo el mismo en tres partes.

En el codigo que voy a usar de ejemplo, simplemente voy a resaltar usando negrita para la parte que coincide y normal para el resto

El codigo para Vcl lo pueden encontrar en el hilo original

Para FMX, las pruebas las hice con un componente TStringGrid. Es necesario que tengamos TStringGrid.DefaultDrawing a False

Luego simplemente metemos un hook para el evento TStringGrid.OnDrawColumnCell

Solo hay unas cosas mas que se deben notar:
  • SearchString es una propiedad de lectura/funcion que devuelve un string. Vendria a ser el string por el cual estamos buscando
  • IsColumnTextHighlightable es una funcion que como se puede ver, devuelve un Boolean que indica si la columna que recibe el evento debe implementar el pintado por defecto o el pintado custom
  • He renombrado algunas variables del codigo original de ecfisa, ya que a mi me confunde mucho los nombres cortos y simples como a, b, c
  • El procedimiento anidado DrawText esta en la version para FMX porque el metodo TCanvas.FillText es bastante "aburrido", ya que requiere de varios parametros que son siempre los mismos. Lo unico que me interesa variar son el Bounds y el Text. La forma mas purista de resolverlo es con un ayudante de clase (class helper) para TCanvas

Código Delphi [-]
procedure TForm1.OnCreate(Sender: TObject);
begin
  StringGrid1.DefaultDrawing := False;
end;

procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas;
  const Column: TColumn; const [Ref] Bounds: TRectF; const Row: Integer; const [Ref] Value: TValue;
  const State: TGridDrawStates);

  procedure DrawText(Bounds: TRectF; const LeftDelta: Single; const Text: string);
  begin
    Bounds := RectF(LeftDelta, Bounds.Top, Bounds.Right, Bounds.Bottom);
    Canvas.FillText(Bounds, Text, False, 1, [], TTextAlign.Leading);
  end;
var
  Handled: Boolean;
  StringLeft, StringMiddle, StringRight, CellStringValue: string;
  p: Integer;
  LeftBoundDelta: Single;
  FontStyles: TFontStyles;
begin
  Handled := False;
  try
    if not IsColumnTextHighlightable(Column) then
      Exit;

    CellStringValue := Value.AsString;

    if not AnsiStartsText(SearchString, CellStringValue) then
      Exit;

    p := AnsiPos(AnsiUpperCase(SearchString), AnsiUpperCase(CellStringValue));
    if p <> 0 then
    begin
      StringLeft := Copy(CellStringValue, 1, p - 1);
      StringMiddle := Copy(CellStringValue, p, Length(SearchString));
      StringRight := Copy(CellStringValue, p + Length(SearchString), MaxInt);

      Canvas.Font.Assign(StringGrid1.TextSettings.Font);
      Canvas.Fill.Color := TAlphaColorRec.Black;
      FontStyles := StringGrid1.TextSettings.Font.Style;

      LeftBoundDelta := Bounds.Left + 2;
      Canvas.Font.Style := FontStyles;
      DrawText(Bounds, LeftBoundDelta, StringLeft);

      LeftBoundDelta := LeftBoundDelta + Canvas.TextWidth(StringLeft);
      Canvas.Font.Style := [TFontStyle.fsBold];
      DrawText(Bounds, LeftBoundDelta, StringMiddle);

      LeftBoundDelta := LeftBoundDelta + Canvas.TextWidth(StringMiddle);
      Canvas.Font.Style := FontStyles;
      DrawText(Bounds, LeftBoundDelta, StringRight);
      Handled := True;
    end;
  finally
    if not Handled then
      StringGrid1.DefaultDrawColumnCell(Canvas, Column, Bounds, Row, Value, State);
  end;
end;

Efecto conseguido en un TGrid FMX:



Efecto conseguido en un TDBGrid Vcl


Casimiro Notevi 28-07-2016 09:48:34

^\||/^\||/^\||/

dec 28-07-2016 11:17:45

Hola,

¡Muchas gracias por compartirlo Agustín! :)

ecfisa 28-07-2016 16:48:29

Hola Agustín.

Muchas gracias por el aporte ^\||/

Saludos :)


La franja horaria es GMT +2. Ahora son las 10:53:21.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi