Внешний вид сайта:

CheckBox внутри DBGrid

Есть способ разместить CheckBox в DBGrid для редактирования булевых полей в наборе данных. Предположим, что Вы имеете булево поле в наборе данных. По умолчанию, DBGrid отображает такое поле как True или False в зависимости от значения.

Создадим простое приложение.

Для начала запустим Delphi и разместим на форме TDBGrid, TADOTable, TADOConnection и TDataSource. Оставим все имена, как их определил Delphi. Используйте Инспектор Объектов, чтобы установить свойство ADOConnection компонента ADOConnection1DBGrid1 к DataSource1, DataSource1 к ADOTable1 и наконец, ADOTable1 к ADOConnection1. Свойство TableName компонента ADOTable1 должно указывать на таблицу, в которой мы имеем булево поле (например, Winner).

Если Вы установили все свойства правильно, то когда Вы запустите приложение (если свойство Active компонента TADOTable1 установлено в True), Вы должны видеть это:

Без CheckBox

Что же нужно сделать для того, чтобы наше приложение выглядело, как это, ниже:

С CheckBox

Выберите TDBCheckBox на палитре компонентов и поместите его где-нибудь на форме.

Затем установите его свойство Visible в False. Измените его свойство Color на тот же самый цвет, что и DBGrid1, чтобы он гармонировал с сеткой и удалите Caption. И, что не менее важно, удостоверьтесь, что DBCheckBox1 связан с DataSource1 и с полем (DataSource = DataSource1, DataField = Winner).

Обратите внимание, что все вышеперечисленные свойства могут быть установлены в событии OnCreate формы, например:

procedure TForm1.FormCreate(Sender: TObject);
begin
 DBCheckBox1.DataSource := DataSource1;
 DBCheckBox1.DataField  := 'Winner';
 DBCheckBox1.Visible    := False;
 DBCheckBox1.Color      := DBGrid1.Color;
 DBCheckBox1.Caption    := '';

 //будет разъяснено ниже в статье
 DBCheckBox1.ValueChecked := 'Да'; 
 DBCheckBox1.ValueUnChecked := 'Нет'; 
end;

Далее более интересная часть. При редактировании булева поля в DBGrid, мы должны удостовериться, что DBCheckBox1 помещен в ячейку DBGrid, в которой отображается булево поле. Для остальной части сетки булево поле также должно быть представлено каким-либо изображением (истинного или ложного значения). Это означает, что мы нуждаемся, как минимум в двух изображениях: одно для истинного значения (True) и одно для ложного значения (False). Самый легкий способ выполнить это состоит в том, чтобы использовать функцию Windows API DrawFrameControl, чтобы рисовать непосредственно на холсте DBGrid.

Вот код в обработчике события OnDrawColumnCell, которое происходит, когда сетка должна перерисовывать ячейку:

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;

Чтобы закончить это действие, мы должны удостовериться, что DBCheckBox1 невидим, когда мы покидаем ячейку.

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

Мы нуждаемся еще в обработке двух событий: перехват нажатия клавиатуры и нажатие на Пробел должен изменять состояние 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;

И, наконец, последнее. Это может быть соответствующий заголовок CheckBox, когда пользователь переключает его. Обратите внимание, что DBCheckBox имеет два свойства (ValueChecked и ValueUnChecked), которые определяют значение поля, представленное переключателем. В нашем случае мы можем записать ValueCheckedДа, а ValueUnChecked – Нет.

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

Это все! Запустите проект и проверьте действие переключателя.

Комментарии

Нет комментариев. Ваш будет первым!