dbgrid的特殊使用(100分)

  • 主题发起人 主题发起人 nacheng
  • 开始时间 开始时间
N

nacheng

Unregistered / Unconfirmed
GUEST, unregistred user!
如何实现dbgrid中每条记录前面加个复选框,并可以实现任意选中多个删除
 
高手实现下
 
你这是什么空件啊
 
怎么没有 人,高手都去哪里了
 
  Delphi中向TDBGrid添加组件是一件十分麻烦的事情。笔者在这里向大家介绍一种利用WIN32 API函数在TDBGRID中嵌入CHECKBOX组件的方法。
  TDBGrid部件是用于显示和编辑数据库表中记录信息的重要部件,它是我们在程序设计过程中要经常使用的一个强有力的工具。TDBGrid具有很多重要的属性,我们可以在程序设计阶段和程序运行过程中进行设置。TDBGrid部件中有很多重要的属性,我们在这里重点介绍Option属性和DefaultDrawing属性,其他属性及其设置方法请参看联机帮助文件。
  Options属性:它是TDBGrid部件的一个扩展属性,在程序设计阶段设置Options属性可以控制TDBGrid部件的显示特性和对事件的响应特性。
  DefalultDrawing属性:该属性是布尔型属性,它用于控制网格中各网格单元的绘制方式。在缺省情况下,该属性的值为True,也就是说Delphi使用网格本身缺省的方法绘制网格中各网格单元,并填充各网格单元中的内容,各网格单元中的数据根据其对应的字段部件的DisplayFormat属性和EidtFormat属性进行显示和绘制。如果DefaulDrawing属性被设置为False,Delphi不会自动地绘制网格中各网格单元和网格单元中的数据,用户必须自己为TDBGrid部件的OnDrawDataCell事件编写相应的程序以用于绘制各网格单元和其中的数据。
  需要注意的是,当一个布尔字段得到焦点时,TDBGrid.Options中的 gdEditing属性不能被设置成为可编辑模式。另外,TDBGrid.DefaultDrawing属性不要设置为FALSE,否则,就不能得到网格中画布属性的句柄。
  程序设计开始时就应考虑:需要设定一变量来存储原始的 TDBGrid.Options的所有属性值。这样,当一boolean字段所在栏得到焦点时将要关闭TDBGrid.Options中gdEditing的可编辑模式。与此相对应,若该栏失去焦点时,就要重新恢复原始的 TDBGrid.Options的所有属性值。
  在实例中可以通过鼠标点击或敲打空格键改变布尔值,这样就需要触发TDBGrid.OnCellClick事件和TDBGrid.OnKeyDown事件。因为这两个事件都是改变单元格中逻辑字段的布尔值,所以为了减少代码的重复最好创建一个私有过程(SaveBoolean;)来完成逻辑值的输入,以后,在不同的事件中调用此过程即可。
  对 TDBGrid.OnDrawColumnCell事件的处理是整个程序的关键。处理嵌入组件的显示的传统方法是:在表单上实际添加组件对象,然后对组件的位置属性与网格中单元格的位置属性进行调整,以达到嵌入的视觉效果。这种方法虽然可行但代码量大,实际运行时控制性很差。笔者采用的方法是充分利用WIN32 API函数:DrawFrameControl(),由于此函数可以直接画出Checkbox组件,所以就无须在表单中实际添加组件。如何使用API函数:DrawFrameControl()是本程序技巧所在。
  在TDBGrid.OnDrawColumnCell事件中,我想大家会注意到:设定一个整型数组常数,而这个返回的整数值是与布尔值相一致的,如果字段是逻辑字段,则只将其布尔值放入数组中,提供给DrawFrameControl()函数中的状态参数进行调用,从而实现了Checkbox组件在网格中的嵌入效果。
  源代码如下:
  type
   TForm1 = class(TForm)
    DataSource1: TDataSource;
    Table1: TTable;
    DBGrid1: TDBGrid;
    procedure DBGrid1DrawColumnCell(Sender: TObject;
          const Rect: TRect;
DataCol: Integer;
          Column: TColumn;
State: TGridDrawState);
    procedure DBGrid1ColEnter(Sender: TObject);
    procedure DBGrid1ColExit(Sender: TObject);
    procedure DBGrid1CellClick(Column: TColumn);
    procedure DBGrid1KeyDown(Sender: TObject;
var Key: Word;
          Shift: TShiftState);
   private
    { Private declarations }
    OriginalOptions : TDBGridOptions;
    procedure SaveBoolean;
   public
    { Public declarations }
   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);
    DrawFrameControl(DBGrid1.Canvas.Handle,
             Rect,
             DFC_BUTTON,
             CtrlState[Column.Field.AsBoolean]);
   end;

  end;

  procedure TForm1.DBGrid1ColEnter(Sender: TObject);
  begin

   // 确保该栏是逻辑字段
   if DBGrid1.SelectedField.DataType = ftBoolean then

   begin

    OriginalOptions := DBGrid1.Options;
    DBGrid1.Options := DBGrid1.Options - [dgEditing];
   end;

  end;

  procedure TForm1.DBGrid1ColExit(Sender: TObject);
  begin

   //确保该栏是逻辑字段
   if DBGrid1.SelectedField.DataType = ftBoolean then

    DBGrid1.Options := OriginalOptions;
  end;

  procedure TForm1.DBGrid1CellClick(Column: TColumn);
  begin

   //确保该栏是逻辑字段
   if DBGrid1.SelectedField.DataType = ftBoolean then

    SaveBoolean();
  end;

  procedure TForm1.DBGrid1KeyDown(Sender: TObject;
             var Key: Word;
Shift: TShiftState);
  begin

   //确保该栏是逻辑字段和空格键在键盘中被敲击
   if ( Key = VK_SPACE ) and
     ( DBGrid1.SelectedField.DataType = ftBoolean ) then

    SaveBoolean();
  end;

  procedure TForm1.SaveBoolean;
  begin

   DBGrid1.SelectedField.Dataset.Edit;
   DBGrid1.SelectedField.AsBoolean :=not DBGrid1.SelectedField.AsBoolean;
   DBGrid1.SelectedField.Dataset.Post;
  end;

首先把DBGRID 的OPTIONS 的 dgMultiSelect属性设置成 true;
然后用类似下面的代码
if dbGrid1.SelectedRows.Count>0 then

begin

Gauge1.Visible := true;
Gauge1.MaxValue := dbGrid1.SelectedRows.Count;
Bbt_AddUser_New.Enabled := false;
try
with dbGrid1.DataSource.DataSetdo

begin

for i := 0 to dbGrid1.SelectedRows.Count-1do

begin

GotoBookmark(pointer(dbGrid1.SelectedRows.Items));
//你自己的处理代码,每次走一条记录,从选择的第一条开始
Gauge1.Progress := Gauge1.Progress + 1;
end;

end;

finally
Gauge1.Visible := false;
Bbt_AddUser_New.Enabled := true;
end;

end
else

begin

Application.MessageBox('请选择要重新上传的流水!','提示',MB_OK + MB_ICONWARNING);
end;

删除选中行:
dbgrid中的options下的rowselect和alwaysshowselect设为true
if DBGrid1.SelectedRows.Count > 0 then

DBGrid1.SelectedRows.Delete
else
//删除当前行
DBGrid1.DataSource.DataSet.Delete;
 
感谢楼上的好东东啊
学习了
 
总的来说,没有DbGridEh来得方便,只要设置一下属性就OK了。
 
后退
顶部