Você está na página 1de 3

CheckBox dentro de um DBGrid

Veja neste artigo, como adicionar um CheckBox em um componente DBGrid.


A seguir, veremos como colocar um check box em um DBGrid. Criar interfaces do usurio visualmente mais atraentes para editar campos boolean dentro de um DBGrid. Este o primeiro artigo da srie de artigos chamada "Adding components to a DBGrid" (Adicionando componentes a um DBGrid). A idia aqui, mostrar como colocar quase qualquer controle Delphi (componente visual), em uma clula de um DGBrid. Se no estiver familiarizado com a idia, por favor, leia antes o artigo acima mencionado. CheckBox em um DBGrid? Como vimos no artigo anterior, h muitos modos (e razes) para considerarmos a personalizao das sadas de um DBGrid: suponha que existe um campo boolean no dataset. Por padro, 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 pudssemos usar um "verdadeiro" controle check box, para habilitar a edio de estes campos. Criando uma aplicao exemplo Para comear, inicie o Delphi e, no formulrio inicial padro 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 formulrio (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 aplicao (desde que a propriedade Active do componente ADOTable1 seja True) dever obter o seguinte: O que voc precisa reparar" na figura anterior que, por padro, 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 ns. Para mostrar um check box dentro de uma clula de um DBGrid, precisaremos fazer com que um fique disponvel em tempo de execuo. Selecione Data controls" na Component Palette, e escolha um TDBCheckbox. Coloque um em qualquer lugar do formulrio (no importa onde, desde que a maior parte do tempo estar invisvel ou flutuando por cima do grid). O TDBCheckBox um controle alerta a dados (data-aware control), que permite ao usurio 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 formulrio: 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 clula do DBGrid que exibe o campo boolean. Para o resto das clulas (no focalizadas), contendo os campos boolean (na coluna "Winner"), precisamos prover alguma representao 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 fcil de realizar isto, usar a funo DrawFrameControl da Windows API, para desenhar diretamente na tela do DBGrid. A seguir, o cdigo no manipulador de evento OnDrawColumnCell do DBGrid, que acontece quando o grid precisa pintar uma clula. 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 invisvel quando sairmos da clula: 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 edio, todas as teclas pressionadas vo para a clula do DBGrid, temos que garantir que sero 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 prxima clula 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 marcao ou desmarcao do usurio. 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 contm '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;