Canvas Grid

Tempo de leitura: 7 minutos

E aí brutaiada, tudo certo?

Depois de muito tempo hibernando, o Bruto do Delphi está de volta. E se vocês acham que eu esqueci do que eu prometi no último post, vocês se enganaram. Hoje, utilizando o que aprendemos no último post e algumas coisinhas mais, vamos personalizar um DBGrid e adicionar algumas funcionalidades interessantes ao mesmo. Vamos começar estudando o evento DrawColumnCell do nosso DBGrid , que vai ser onde grande parte da mágica vai acontecer.

procedure TFrm_Receber.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);

Antes de destrincharmos os parâmetros de entrada desse evento temos que entender quando esse evento é disparado. Ele ocorre toda vez que uma célula precisa ser (re)desenhada. Isso quer dizer:  desenho inicial, nova linha visível, linha/coluna selecionada/deselecionada ou célula que não estava visível passa a estar visível. E lembrando que esse evento é disparado para cada célula que precisa ser desenhada, desta forma, num grid de 5 linhas e 10 colunas para o desenho inicial esse evento será chamado 50 vezes (se todas as células estiverem visíveis). Agora vamos aos parâmetros:

  • Sender é o objeto que chamou o evento. Normalmente é o seu DBGrid a não ser que você tenha ligado vários DBGrids ao mesmo método, mas não costuma acontecer.
  • Rect é o retângulo da célula que está sendo desenhada, idealmente você só pode desenhar dentro dessa área.
  • DataCol é o índice da coluna que está sendo desenhada, importante citar que a contagem de colunas começa do zero.
  • Column indica o objeto coluna que está sendo desenhado, nele você tem acesso ao título da coluna, ao campo, ao alinhamento e tudo o que foi definido no editor de colunas do DBGrid.
  • State define o estado de célula que está sendo desenhada. Se ela está selecionada, se ela tem o foco, se a linha está selecionada, se ela é uma coluna fixada, etc…

Agora que já conhecemos a fundo o evento onDrawColumnCell, só estamos a mais dois passos de transformarmos nossos DbGrids. Um deles é a propriedade DefaultDrawing, se essa propriedade do seu DBGrid for true ele vai desenhar tudo pra você antes de chamar o evento onDrawColumnCell. Se for false, ele vai apenas desenhar o fundo da célula para você e setar as propriedades do canvas para o parametrizado na sua coluna. O outro é o método DefaultDrawColumnCell. Utilizando o Canvas do DbGrid ele desenha a célula para você.

Vamos então colocar a mão na massa. Para os nossos exemplos, vou utilizar a base de dados EMPLOYEE.FDB que vem na instalação do Firebird 2.5, mas você pode usar qualquer outra, se você quiser. Nosso exemplo começa com uma conexão setada com a base e uma query dando um select * from employee. Mais ou menos como na Figura 1.

canvas grid
Figura 1

Lembrando que eu adicionei os todos campos na query e todas as colunas no DBGrid. Ah! Se você não sabe fazer uma conexão com o banco de dados ou dar um select em uma query pode parar por aqui, não seja burro de tentar aprender a desenhar num DBGrid se você não sabe nem como puxar dados para o DBGrid. Abre aquele que sabe tudo (o Google) e aprende primeiro como conectar em uma base de dados, depois você volta aqui. Isso, pode ir, eu espero. E se você tá torcendo o nariz por eu ter adicionado campos persistentes, que não é boa prática, que não é legal, que blá blá blá, vá se f***, simples assim! O Bruto trabalha desse jeito e se você que aprender com o Bruto vai aprender do jeito dele. E também, isso é só um exemplo, boas práticas em um exemplo é mesma coisa que um programador Java: inútil.

Começaremos com um exemplo simples: trocar a fonte de todos os empregados que moram nos estados unidos para azul. No evento onDrawColumnCell coloque o seguinte código, o resultado vai ser o mostrado na Figura 2:

if IBQuery1JOB_COUNTRY.AsString = 'USA' then
begin
  DBGrid1.Canvas.Font.Color := clBlue;
  DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;

img2
Figura 2

Explicando rapidamente, se o campo JOB_Country for ‘USA’ eu troco a cor da fonte do Canvas do DBGRID1 para azul e peço para o método DefaultDrawColumnCell fazer o serviço pra mim. Ai você deve estar indignado: “Mas bruto, ele pintou a linha inteira, e não só a coluna JOB_COUNTRY”. É claro que ele fez isso seu zé mané, você testou o valor da coluna e não se ele estava desenhando aquela coluna ou não. Como eu disse antes e você não deve ter prestado atenção, ele passa nesse método para cada célula, de cada linha. E em todas as células de todas as linhas em que o JOB_COUNTY é USA o if retorna true. Se você quiser mexer com apenas uma coluna da linha terá que fazer mais ou menos como no exemplo abaixo, que vai deixar negrito o nome de todos os funcionários que ganham mais de 70 mil.

if IBQuery1JOB_COUNTRY.AsString = 'USA' then
  DBGrid1.Canvas.Font.Color := clBlue;
if IBQuery1SALARY.AsFloat > 70000 then
  if Column.FieldName = 'FIRST_NAME' then
   DBGrid1.Canvas.Font.Style := [fsBold];

DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
Canvas Grid
Figura 3

Receba conteúdos como este

Não perca nenhum conteúdo aqui do blog, faça como milhares de assinantes, receba gratuitamente nossas atualizações!>

Claro que você notou que eu tirei o DefaultDrawColumnCell do IF e nada aconteceu. Tinha colocado ele no if anteriormente por economia para ele não chamar o método desnecessariamente. Mas agora ia complicar demais verificar se entrou em um ou outro e chamar ele duas vezes seria idiotice. E você, na ânsia de deixar seu sistema carnavalesco, vai me perguntar: “Tem como pintar o fundo da linha de amarelo em alguma situação?”. Ai eu vou ter que responder: “Tem sim, cacilda”. Parece que você ou ainda não entendeu a lógica da coisa ou não lembra do artigo anterior. Tudo o que eu alterar no Canvas do DBGrid será utilizado para desenhá-lo no método DefaultDrawColumnCell. E eu já ensinei a alterar o fundo das coisas, use o Brush. Vamos ao exemplo, vamos deixar amarelo o fundo das linhas em que o JOB_GRADE for igual a 5.

if IBQuery1JOB_COUNTRY.AsString = 'USA' then 
  DBGrid1.Canvas.Font.Color := clBlue;
if IBQuery1SALARY.AsFloat > 70000 then 
  if Column.FieldName = 'FIRST_NAME' then 
    DBGrid1.Canvas.Font.Style := [fsBold];
if IBQuery1JOB_GRADE.AsInteger = 5 then 
  DBGrid1.Canvas.Brush.Color := clYellow;

DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
Canvas Grid
Figura 4

Lindo né ? SQN. Bem, acho que você pegou a ideia né,  alterei no canvas, chamei o DefaultDrawColumnCell, ele faz o trabalho todo e você leva a glória para casa. Sabendo disso é possível fazer várias outras coisas com o seu grid e demonstrar informações de modo visualmente mais rico, é só ter um pouco de imaginação. Como por exemplo Grids zebrados.

É, isso aí, ótima ideia. Vou finalizar esse artigo lançando um desafio, quero saber quem, utilizando apenas o que aprendemos nesse artigo, consegue criar um grid zebrado na linha (uma linha colorida, uma linha branca) e outro zebrado na coluna (uma coluna colorida e uma coluna branca). “Mas preai, como assim finalizando? Você não ia ensinar como deixar nosso Grid mais profissional? Coisas maravilhosas, inimagináveis e espetaculares? O que é isso, pegadinha do malandro, ié ié?”.

Calma jovem gafanhoto… Dá uma olhada nesse texto ai em cima, está grande, eu estou cansado de escrever, você tá cansado de ler, meu revisor vai se cansar ao revisar e o Mourão vai se cansar ao editorar o texto. (“Estou mesmo, que merda de texto grande.” Rodrigo Mourão).  Vou separar tudo o que eu tenho pra te ensinar em dois (ou quem sabe 3) posts. Mas pode ficar tranquilo que os posts vão sair um atrás do outro. O segundo post mesmo a essa hora já está meio escrito. Na verdade deixa eu ir me despedindo que eu ainda tenho muita coisa pra escrever.

Até a próxima.