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