我的问题是如何在 Delphi 7 的 dbgrid 中设置一个带有复选框项目的列。
提前致谢。
我测试过的最简单最完整的方法如下:
在您单元的私有部分,声明一个用于保留网格选项的全局。它将用于在进入复选框列时临时禁用文本编辑后恢复 - 因为这可能是 Jordan Borisovin 提到的关于 delphi.about.com 文章的小错误之一
private
GridOriginalOptions : TDBGridOptions;
在 OnCellClick 事件中,如果字段为布尔值,则切换并将更改发布到数据库
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
if (Column.Field.DataType=ftBoolean) then
begin
Column.Grid.DataSource.DataSet.Edit;
Column.Field.Value:= not Column.Field.AsBoolean;
Column.Grid.DataSource.DataSet.Post;
end;
end;
为网格的布尔字段绘制复选框
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
CtrlState: array[Boolean] of integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED) ;
begin
if (Column.Field.DataType=ftBoolean) then
begin
DBGrid1.Canvas.FillRect(Rect) ;
if (VarIsNull(Column.Field.Value)) then
DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_INACTIVE)
else
DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, CtrlState[Column.Field.AsBoolean]);
end;
end;
现在是新部分,在布尔列中禁用单元格编辑。在 OnColEnter 和 OnColExit 事件上:
procedure TForm1.DBGrid1ColEnter(Sender: TObject);
begin
if Self.DBGrid1.SelectedField.DataType = ftBoolean then
begin
Self.GridOriginalOptions := Self.DBGrid1.Options;
Self.DBGrid1.Options := Self.DBGrid1.Options - [dgEditing];
end;
end;
procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
if Self.DBGrid1.SelectedField.DataType = ftBoolean then
Self.DBGrid1.Options := Self.GridOriginalOptions;
end;
更重要的是,处理用于切换复选框的空格键
procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if ((Self.DBGrid1.SelectedField.DataType = ftBoolean) and (key = VK_SPACE)) then
begin
Self.DBGrid1.DataSource.DataSet.Edit;
Self.DBGrid1.SelectedField.Value:= not Self.DBGrid1.SelectedField.AsBoolean;
Self.DBGrid1.DataSource.DataSet.Post;
end;
end;
而已!
如果您使用的是 TClientDataset+TDatasetProvider+TDataset,您可以在数据数组变体到达客户端数据集之前对其进行操作,并包含一个不可更新的布尔字段。
完成后,您只需使用 OnDrawColumnCell 事件在网格上绘图。在这里,我没有使用 CheckBox,而只是使用位图(当用户单击它时,它会变为选中/未选中)。
请原谅我将此作为答案发布,我还没有 50 名声望来添加评论。
Mihai MATEI的答案非常接近罕见的(如真正有效的)解决方案,除了它出现错误的用例。
每当用户在网格上的第一个操作是单击复选框时,第一次单击将起作用,但第二次单击将显示底层 DBGrid 编辑器。
发生这种情况是因为需要初始化“GridOriginalOptionsmechan”机制。为此,只需在网格的 OnEnter 事件中添加以下代码:
procedure TForm1.DBGrid1Enter(Sender: TObject);
begin
DBGrid1ColEnter(Sender);
end;
而已!
好的,我用 这篇文章来解决我的问题。好的,但问题是它没有按应有的方式工作。所以我在代码中改变了我的逻辑。并通过将 dbgrid 中选定的行保存在列表中来实现它。