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