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