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

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

Выберите 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;
Это все! Запустите проект и проверьте действие переключателя.
Комментарии