CheckBox no DBGrid do Delphi


Simular CheckBox no DBGrid, sempre foi algo muito trabalhoso, mas existe uma jeito simples e rápido de fazer essa simulação. Já mostrei antes outras maneiras mas recebi alguns e-mails falando que não conseguiram vamos la então:
Vamos precisar de:
  • TDBGrid
  • TClientDataSet
  • TDataSource
No ClientDataSet1, faça:
Dê um duplo clique no ClientDataSet1, ou clique com o botão direito do mouse, e escolha a opção Fields Editor ...

Crie um campo com as seguintes características:
Tipo (type): String Tamanho (size): 1 
Nome (name): PEDIR
Após o preenchimento, clique em OK, e em seguida feche a janela, onde o campo PEDIR está aparecendo. Adicione o campo no TDBGrid com algum nome sugestivo.

Código abaixo deve fica no evento de OnDrawColumnCell do TDBGrid, Esse código irá utilizar o canvas para desenhar os checkBox dentro do nosso grid, e na primeira linha delimitamos para ser apenas na primeira coluna. 
procedure TFSistema.dbgrPrincipalDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  lR: TRect;
  lCheck: integer;
begin
  if Assigned(CDSGenerico.FindField('PEDIR')) and (Column.Index = 0) then begin
    if (CDSGenerico.FieldByName('PEDIR').Value = 1) then
      lCheck := DFCS_BUTTONCHECK or DFCS_CHECKED
    else
      lCheck := DFCS_BUTTONCHECK;
    dbgrPrincipal.Canvas.FillRect(Rect);
    lR := Rect;
    InflateRect(lR, -2, -2);
    DrawFrameControl(dbgrPrincipal.Canvas.Handle, lR, DFC_BUTTON, lCheck);
  end else
    dbgrPrincipal.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;

Para executar ação TRUE ou FALSE (No meu caso 1 ou 0) no CheckBox use o procedimento OnDblClik ou no OnCellClick do DBGrid, ( Normalmente utilizo no duplo clique para evitar que cada vez que clicar no dbgrid marque a opção), aqui um código já familiar apenas uma validação se o campo estiver 1 ou True joga para 0 ou False!
procedure TFSistema.dbgrPrincipalDblClick(Sender: TObject);
begin
  if not Assigned(CDSGenerico.FindField('PEDIR')) then
    ModalResult := mrOk
  else begin
    CDSGenerico.Edit;
    CDSGenerico.FieldByName('PEDIR').AsInteger := IfThen(CDSGenerico.FieldByName('PEDIR').asinteger = 1, 0, 1);
    CDSGenerico.Post;
  end;
end;

tam, tam, tam, tammmmmm 

Resultado

20 comentários:

  1. Boa tarde Ana Paula

    Fiz tudo certinho, mas o ticado dentro do checkbox não desenhou.

    Sera que esta faltando comando?

    obrigada

    ResponderExcluir
    Respostas
    1. O código para desenhar o checkBox você colocou onde? Tem que esta no OnDrawColumnCell.
      Baixa o exemplo acredito que ira ajudar.

      Excluir
  2. Boa Tarde...
    Estou com o mesmo problema do Cristiano...
    Fiz os passos corretamente com umas excessões...
    Ao invés do ClientDataSet, estou usando TQuery...
    E não sei se eu entendi direito o exemplo, mas no meu eu não tenho o campo fisicamente criado na tabela...
    Criei somente na TQuery e no TDBGrid um campo check e do tipo boolean...
    Pois bem, ele desenhou perfeitamente o checkBox na coluna... Porém quando eu clico nele, eu dou um Query.Edit;
    Seto como true ou false verificando primeiro o seu valor, dou um Query.Post; e na hora de pintar o "Checked" ele entra na função DrawCell como se o campo fosse sempre false...
    Estou esquecendo de algo?

    ResponderExcluir
    Respostas
    1. Ola! Bom Dia!
      Confesso que nunca utilizei essa funcionalidade com campo não físico direto no componente de acesso a banco, nesses casos sempre utilizo um "DataSetProvider" para auxiliar e crio o campo do tipo "InternalCalc" ou direto no SQL ex:
      select 0 as SEL, C.CODCIDADE, C.CIDADE
      from CIDADES C

      Mas normalmente já que é bem utilizado em relatórios ou telas de consulta jogo direto no “TClientDataSet” por questão de agilidade para o usuário.

      Excluir
  3. Função IfThen declaro como na uses?

    ResponderExcluir
    Respostas
    1. Charles Bandeira: declara a unit "Math" mas "uses" de baixo

      Excluir
  4. Show! Excelente post Ana Paula, funcionou certinho.

    ResponderExcluir
  5. Ola Ana Paula estou precisando de uma rotina que faz justamente isso. vou testar aqui ver se dar certo.

    ResponderExcluir
    Respostas
    1. Tem o exemplo no link abaixo do post, se quiser da uma olhada http://www.4shared.com/rar/IMW54N2Yce/000007.html

      Excluir
  6. Alguém sabe como selecionar todos os checks ao mesmo tempo? e todos os registros do grid ficarem selecionados?

    ResponderExcluir
    Respostas
    1. Normalmente utilizo laço de repetição, Coloco dois botão "Marcar todos" e outro "Desmarcar todos" como no exemplo abaixo:

      TbTabela.first;
      while not TbTabela.Eof then begin
      TbTabela.Edit;
      TbTabela.FieldByName('SELECAO').asInteger := IfThen(Sender = BtnMarcarTodos, 1, 0);
      TbTabela.Post;
      TbTabela.Next;
      end;

      Excluir
  7. Olá Ana Paula, fiz o código como você explicou, porém quando é criado o campo PEDIR ele é String, mas depois quando edita no OnDblClik é passado como Integer e da a mensagem que '' is not integer value

    ResponderExcluir
    Respostas
    1. Sim, dependendo da versão do Delphi ocorre esse erro sim, é só criar o campo com o tipo de "Integer" não tem problema e ainda é melhor que "string"

      Excluir
  8. Excelente. Funcionou perfeitamente, só uma observação: lembrando que a propriedade do DBGRID (dgRowSelect) deve estar FALSE e consequentemente a propriedade (dgEditing) deve estar TRUE.

    ResponderExcluir
    Respostas
    1. Boa noite!
      Eu por costume sempre deixo o dgRowSelect como True, e o dgEditing como False! (Isso acredito que seja mais questão de padrão que é acostumado a trabalhar)
      Oque ira fazer o campo trocar de valor é o Duplo clique!

      Excluir
  9. Bom dia Ana Paula. Primeiro parabéns pelo seu post, muito bom!!! o exemplo é funcional, mas me diga como faço para não exibir os valores 0 ou 1 na coluna? No meu exemplo fica aparecendo essa informação bem ao lado do checkbox

    ResponderExcluir
    Respostas
    1. Buenas! Obrigada, olha nunca presenciei isto de ficar o 0 ou 1 ao lado! Em baixo post tem o exemplo para Download, tenta verificar se nele também está aparecendo o 0 ou 1 em seu PC

      Excluir
  10. Show de bola, parabéns! Usei agora mesmo e deu super certo

    ResponderExcluir
  11. NEM o GPT ensinou tao bem como voce, so vim aqui pra agradecer a ajuda!

    ResponderExcluir