CheckBox dentro de um DBGrid

Veja neste artigo, como adicionar um CheckBox em um componente DBGrid. Acesso exclusivo para Assinantes.

A seguir, veremos como colocar um check box em um DBGrid. Criar interfaces do usuário visualmente mais atraentes para editar campos boolean dentro de um DBGrid.

Este é o primeiro artigo da série de artigos chamada "Adding components to a DBGrid" (“Adicionando componentes a um DBGrid”). A idéia aqui, é mostrar como colocar quase qualquer controle Delphi (componente visual), em uma célula de um DGBrid. Se não estiver familiarizado com a ideia, por favor, leia antes o artigo acima mencionado.

CheckBox em um DBGrid?

Como vimos no artigo anterior, há muitos modos (e razões) para considerarmos a personalização das saídas de um DBGrid: suponha que existe um campo boolean no dataset. Por padrão, o DBGrid exibe campos boolean como "True" ou "False", dependendo do valor do campo. Se você pensa como eu, concordará que será visualmente muito mais atraente se pudéssemos usar um "verdadeiro" controle check box, para habilitar a edição de estes campos.

Criando uma aplicação exemplo

Para começar, inicie o Delphi e, no formulário inicial padrão vazio, coloque um TDBGrid, um ADOTable, um TADOConnection e um TDataSource. Deixe os nomes dos componentes do jeito que o lphi os chamou quando colocados no formulário (DBGrid1, ADOQuery1, AdoTable1,...). Use o Object Inspector para configurar a propriedade ConnectionString do componente ADOConnection1 (TADOConnection), para apontar para o banco de dados de exemplo QuickiesContest.mdb do MS Access.

Conecte o DBGrid1 ao DataSource1, o DataSource1 ao ADOTable1 e finalmente, o ADOTable1 ao ADOConnection1. A propriedade TableName do ADOTable1 deverá apontar para a tabela Articles (para que o DBGrid passe a exibir os registros da mesma). Se você configurou todas as propriedades corretamente, quando rodar a aplicação (desde que a propriedade Active do componente ADOTable1 seja True) deverá obter o seguinte:

O que você precisa “reparar" na figura anterior é que, por padrão, o DBGrid exibe o valor do campo boolean como "True" ou" False", dependendo do valor do campo. O campo que armazena o valor boolean é "Winner". O que iremos mostrar neste artigo, é como fazer para que a figura anterior tenha o seguinte aspecto:

CheckBox em um DBGrid!

Ou, melhor dizendo, um DBCheckBox em um DBGrid.

Ok, aqui vamos nós. Para mostrar um check box dentro de uma célula de um DBGrid, precisaremos fazer com que um fique disponível em tempo de execução. Selecione “Data controls" na Component Palette, e escolha um TDBCheckbox. Coloque um em qualquer lugar do formulário (não importa onde, desde que a maior parte do tempo estará invisível ou flutuando por cima do grid). O TDBCheckBox é um controle alerta a dados (data-aware control), que permite ao usuário selecionar ou de-selecionar um único valor – muito apropriado para campos boolean.

A seguir, configure sua propriedade Visible para False. Altere a propriedade Color do DBCheckBox1 para a mesma do DBGrid (assim se confundirá com a do DBGrid) e remova o Caption. E o mais importante, certifique-se de que o DBCheckBox1 esteja conectado ao DataSource1 e para o campo correto (DataSource = DataSource1, DataField = Winner).

Repare que todos os valores de propriedade do DBCheckBox1, podem ser configurados no evento OnCreate do formulário:

procedure TForm1.FormCreate(Sender: TObject); begin DBCheckBox1.DataSource := DataSource1; DBCheckBox1.DataField := 'Winner'; DBCheckBox1.Visible := False; DBCheckBox1.Color := DBGrid1.Color; DBCheckBox1.Caption := ''; //explicado mais adiante no artigo DBCheckBox1.ValueChecked := 'Yes a Winner!'; DBCheckBox1.ValueUnChecked := 'Not this time.'; end;

O que vem a seguir é a parte mais interessante. Ao editarmos o campo boolean no DBGrid, precisamos ter certeza de que o DBCheckBox1 está posicionado acima ("flutuando") da célula do DBGrid que exibe o campo boolean. Para o resto das células (não focalizadas), contendo os campos boolean (na coluna "Winner"), precisamos prover alguma representação ao vivo do valor boolean (True/False).

Isto significa que precisamos pelo menos desenhar duas imagens: uma para o estado marcado (valor True) e outra para o estado desmarcado (valor False). O modo mais fácil de realizar isto, é usar a função DrawFrameControl da Windows API, para desenhar diretamente na tela do DBGrid.

A seguir, o código no manipulador de evento OnDrawColumnCell do DBGrid, que acontece quando o grid precisa pintar uma célula.

procedure TForm1.DBGrid1DrawColumnCell( Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); const IsChecked : array[Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED); var DrawState: Integer; DrawRect: TRect; begin if (gdFocused in State) then begin if (Column.Field.FieldName = DBCheckBox1.DataField) then begin DBCheckBox1.Left := Rect.Left + DBGrid1.Left + 2; DBCheckBox1.Top := Rect.Top + DBGrid1.top + 2; DBCheckBox1.Width := Rect.Right - Rect.Left; DBCheckBox1.Height := Rect.Bottom - Rect.Top; DBCheckBox1.Visible := True; end end else begin if (Column.Field.FieldName = DBCheckBox1.DataField) then begin DrawRect:=Rect; InflateRect(DrawRect,-1,-1); DrawState := ISChecked[Column.Field.AsBoolean]; DBGrid1.Canvas.FillRect(Rect); DrawFrameControl(DBGrid1.Canvas.Handle, DrawRect, DFC_BUTTON, DrawState); end; end; end;

Para finalizar este passo, precisamos garantir que o DBCheckBox1 esteja invisível quando sairmos da célula:

procedure TForm1.DBGrid1ColExit(Sender: TObject); begin if DBGrid1.SelectedField.FieldName = DBCheckBox1.DataField then DBCheckBox1.Visible := False end;

Precisamos apenas controlar mais dois eventos. Note que no modo de edição, todas as teclas pressionadas vão para a célula do DBGrid, temos que garantir que serão redirecionadas para o CheckBox. No caso de um CheckBox, estamos principalmente interessados nas teclas [Tab] e [Space]. A tecla [Tab] deveria mover o foco de entrada para a próxima célula e a tecla [Space] deveria alternar o estado do CheckBox.

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char); begin if (key = Chr(9)) then Exit; if (DBGrid1.SelectedField.FieldName = DBCheckBox1.DataField) then begin DBCheckBox1.SetFocus; SendMessage(DBCheckBox1.Handle, WM_Char, word(Key), 0); end; end;

E finalmente, o último toque. Seria conveniente que o Caption do checkbox mudasse de acordo com a marcação ou desmarcação do usuário. Note que o DBCheckBox tem duas propriedades (ValueChecked e ValueUnChecked), usadas para especificar o valor do campo representado pelo check box quando for marcado/desmarcado. Minhas propriedades ValueChecked e ValueUnChecked contém 'Yes a Winner!' e 'Not this time', respectivamente.

procedure TForm1.DBCheckBox1Click(Sender: TObject); begin if DBCheckBox1.Checked then DBCheckBox1.Caption := DBCheckBox1.ValueChecked else DBCheckBox1.Caption := DBCheckBox1.ValueUnChecked; end;

Isto é tudo. Rode o projeto e voila... Checkboxs em toda a coluna do campo Winner.

Se você precisar de qualquer ajuda com o código, envie suas perguntas ao Delphi Programming Forum.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados