Esse artigo faz parte da revista Clube Delphi Edição 62. Clique aqui para ler todos os artigos desta edição

DBGrid da VCL.

A Figura 1 mostra o exemplo em execução. Quando o usuário digita um texto no Edit ("R”, por exemplo), filtramos o DataSet correspondente e destacamos as letras digitadas em cada campo do DBGrid. Repare que a busca é feita em qualquer coluna do DBGrid, ou seja, são filtrados todos os registros que começam com "R" em qualquer campo (comprove pela figura). O código também funciona para campos numéricos e datas.

 

Figura1.Procura no DBGrid negrita ocorrências dos caracteres digitados, semelhante à Tool Palette do Delphi 2005

 

Tomei o cuidado de construir o exemplo usando apenas recursos da classe TDataSet, de forma que funcionasse para qualquer descendente que você esteja utilizando em suas aplicações: TClientDataSet, TQuery, TTable, TIBQuery etc. Neste exemplo, utilizei um ClientDataSet ligado pelo FileName ao arquivo employee.xml dos demos do Delphi. Vamos ver como o exemplo funciona. Destacar itens e colorir o DBGrid é algo relativamente simples de ser feito. Podemos usar o seu evento OnDrawColumnCell para pintar manualmente cada célula (veja um artigo completo sobre vários recurso de pintura no DBGrid na edição 44). O grande problema aqui é outro: negritar parte da palavra e continuar a escrever com fonte normal exatamente onde a parte destacada terminada. Calcular coordenadas pelo número de letras não funcionaria, a menos que usássemos uma fonte mono espaçada.

A técnica que usei consiste em usar uma importante função da APIWindows, DrawText. O Delphi usa internamente essa função de baixo nível para pintar vários controles de tela. Por exemplo, quando configuramos o Caption de uma Label, a VCL usa DrawText para "pintar" o texto em um DeviceContext (HDC), nesse caso o Canvas do formulário.

DrawText tem um truque. Podemos usar a função para "simular" a pintura de um texto em uma área delimitada (nesse caso um TRect), apenas para fins de cálculo(basta passar a constante DT_CALCRECT no último parâmetro).Ou seja, chamamos a função como se fossemos pintar algo,mas na verdade o Windows não pinta. Qual a moral?

O TRect, passado no quarto parâmetro, é redimensionado automaticamente para comportar o texto "pintado': Isso é suficiente para saber qual é o espaço necessário para exibir as primeiras letras em negrito e continuar usando texto normal exatamente na coordenada seguinte. De posse dessa informação, usamos normalmente o método TextOut de Canvas. Veja na Listagem 1 o código que deve ser colocado no evento OnDrawColumnCell do seu DBGrid (método DBGrid1DrawColumnCell).

 

Listagem 1.Código para negritar busca no DBGrid

procedure TForm1.DBGrid1DrawColumnCell(

   Sender: TObjeet; eonst Reet: TReet;

   DataCol: lnteger; Column: TColumn;

   State: TGridDrawState):

var

   r1, r2: TReet;

   s1, s2: string;

begin

   if (Edit1.Text = ‘’) or

    (Pos(UpperCase(Edit1.Text).

     UpperCase(Column.Field.AsString)) <> 1) then

        exit;

   r1 := Rect; r2 := Rect;

   s1 := copy(Column.Field.AsString,1,

      length(Edit1.Text));

   DBGrid1.Canvas.FillRect(Rect);

   DBGrid1.Canvas.Font.Color := clRed;

   DBGrid1.Canvas.Font.Style := [fsbold];

   DrawText(DBGrid1.Canvas.Handle,PChar(s1),

      Length(s1), r1,DT_CALCRECT);

   DBGrid1.Canvas.TextOut(r1.Left,r2.Top,s1);

   DBGrid1.Canvas.Font.AssignCDBGrid1.Font);

   s2 := StringReplace(Column.Field.AsString,s1, ‘’, []);

   r2.Left := r1.Right;

   DrawText(DBGridl.Canvas.Handle,pchar(s2),

      length(s2), r2,0);

end;

 

procedure TForm1.Edit1Change(Sender: TObject);

begin

   ClientDataSet1.Filtered := false;

   ClientDataSet1.Filtered := Edit1.Text <> ‘’;

end;

 

procedure TForm1.ClientDataSet1FilterRecord(

   DataSet: TDataSet; var Accept: Boolean);

var

   i: integer;

begin

   for i := 0 to DataSet.FieldCount - 1 do begin

      Accept := Pos(UpperCase(Edit1.Text),

          UpperCase(DataSet.Fields[i].AsString)) = 1;

      if Accep then exit;

   end;

end;

 

Nota: O evento OnDrawDataCell possui funcionalidade semelhante ao OnDrawColumnCell, mas não deve ser mais usado, ele apenas permanece para efeitos de compatibilidade.

 

...

Quer ler esse conteúdo completo? Tenha acesso completo