19 de novembro de 2009

Customizando a aparência de um Grid em Delphi - parte 3

Há alguns dias, tratei num post a customização da aparência de um Grid, onde mostrei alguns conceitos básicos do objeto Canvas do Delphi e C++ Builder, usado para fazer a customização num StringGrid. Os mesmos conceitos são válidos para os DBGrids mas, como há algumas diferenças, vou abordar aqui a customização desse tipo de grid.

A diferença mais importante está nos parâmetros que são passados para o evento de pintura de uma célula:
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState);

No caso do DBGrid, ao invés de nos informar a linha e a coluna que se está desenhando, o evento nos dá o campo atual da query, representado pelo parâmetro Field. Para ficar mais claro o que está acontecendo, a ordem de desenho das células é a seguinte: primeiro, um registro da query é posicionado; depois, o evento de desenho é disparado para cada uma das colunas (os campos ou Fields) selecionados na query. Novos registros são posicionados até que a parte visível do grid esteja completa ou que o fim do result set seja atingido. Com isso, cada novo registro é desenhado numa nova linha e, obviamente, cada campo ocupa uma coluna.

O trecho de código abaixo pinta o valor de um Field numérico de azul (quando positivo) ou vermelho (quando negativo).
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState);
var yCalc, xCalc : integer;
Texto : String;
lCanvas : TCanvas;
DBGrid : TDBGrid;
begin
{ Salva em variáveis locais para facilitar a clareza }
DBGrid := Sender As TDBGrid;
lCanvas := DBGrid.Canvas;

if (not (gdFixed in State) ) and
(Field.FieldName = 'VALOR')
then begin
{ Formata o valor para apresentação }
texto := FormatFloat ('###,##0.00', Field.AsFloat);

{ Cor de fundo para célula depende se está selecionada }
if gdSelected in State then
lCanvas.Brush.Color := clHighlight
else
lCanvas.Brush.Color := DBGrid.Color;

{ Cor do fonte para o campo, de acordo com o valor }
if Field.AsFloat >= 0 then
lCanvas.Font.Color := clBlue
else
lCanvas.Font.Color := clRed;

{ Preenche com a cor de fundo }
lCanvas.FillRect(Rect);

{ Calcula posição para centralizar o texto na vertical }
yCalc := lCanvas.TextHeight (texto);
yCalc := Rect.Top + (Rect.Bottom - Rect.Top - yCalc) div 2;

{ calcula posição para alinha valor numérico à direita }
xCalc := lCanvas.TextWidth (texto);
xCalc := Rect.Right - xCalc - 3;

lCanvas.TextRect (Rect, xCalc, yCalc, texto);
end
else
DBGrid.DefaultDrawDataCell (Rect, Field, State);
end;

Observe que este código precisa tratar apenas o Field que queremos - distinguido pelo nome do campo no banco de dados, ao contrário do código postado a respeito da aparência do StringGrid. Aqui, o tratamento para os demais fields e states é repassado para a função DefaultDrawDataCell do Grid, que cuida de desenhar e formatar as células que não nos interessa customizar.

E é possível determinar o número da linha atual? Há uma propriedade no DataSet chamada RecNo que indica o número sequencial do registro que está atualmente posicionado. Como o TField está associado a um DataSet (query ou table), posso usar o RecNo para, por exemplo, pintar as linhas do grid com cores alternadas, dando o efeito de zebrado:
{ Cor de fundo para as linhas }
if (Field.DataSet.RecNo mod 2) = 0 then
lCanvas.Brush.Color := clSilver
else
lCanvas.Brush.Color := DBGrid.Color;

A diferença entre os eventos OnDrawDataCell e OnDrawColumnCell é que esse segundo recebe um parâmetro com as configurações da coluna do Grid, isto é, um TColumn) ao invés do TField. Como uma das propriedades do TColumn é justamente o Field associado, adaptar o código mostrado neste post é simples. E, de acordo com o help do Delphi, é preferível usar a versão com o TColumn pois a outra é considerada obsoleta.

Embora as funções e propriedades do objeto Canvas tenha sido apresentado num contexto específico nessa série de posts sobre aparência de Grids, os conceitos podem ser usados para trabalhar em qualquer contexto onde haja um Canvas.

Mais Informações
Customizando a aparência de um Grid em Delphi - parte 1 e parte 2

Nenhum comentário :

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.