在网格中添加一个复选框,其OnDrawColumnCell处理程序是通用的

时间:2014-02-28 04:57:04

标签: delphi tdbgrid

继续本question及其非常有用的答案:我在 big 项目中实现了Ken的答案的变体,其中我有类似的代码以多种形式出现。但我注意到我也有一些使用DrawColumnCell处理程序的表单如下

procedure TEditDocket.DBGrid1DrawColumnCell(Sender: TObject;
           const Rect: TRect; DataCol: Integer; Column: TColumn;
           State: TGridDrawState);
var
 DrawRect: TRect;

begin
 if column.Index  = 3 then
  begin
   DrawRect:= Rect;
   drawrect.left:= rect.left + 24;
   InflateRect (DrawRect, -1, -1);
   dbgrid1.Canvas.FillRect (Rect);
   DrawFrameControl (dbgrid1.Canvas.Handle, DrawRect, DFC_BUTTON,
                 ISChecked[Column.Field.AsInteger]);
  end
 else dbgrid1.DefaultDrawColumnCell (Rect, DataCol, Column, State);
end;

如何将上述代码与一般的OnDrawColumnCell处理程序结合起来?是否可以使用额外的参数定义通用处理程序(这将是列索引;如果它是-1,那么上面的代码将不会执行)?我如何将这样的参数传递给处理程序?

2 个答案:

答案 0 :(得分:1)

我看到(从评论链中)你想要调用泛型或(在某些情况下)也调用复选框绘图的代码。

  

通用的OnDrawColumnCell处理程序处理单元格的背景颜色。如何扩展它以创建一个处理程序,它也将在需要时绘制复选框?顺便说一下,通用代码必须在复选框代码之前调用,而不是在。

之后调用

这实际上非常简单。使用正确的签名(通用签名和复选框1)定义两种方法(代码未经测试!)。但是,只将通用事件连接到TDBGrid.OnDrawColumnCell事件 - 如果需要,将复选一个复选框:

// Generic (from my other post) - notice method name has changed
procedure TDataModule1.GenericDrawColumnCell(Sender: TObject; 
  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  RowColors: array[Boolean] of TColor = (clSilver, clDkGray);
var
  OddRow: Boolean;
  Grid: TDBGrid;
begin
  if (Sender is TDBGrid) then
  begin
    Grid := TDBGrid(Sender);
    OddRow := Odd(Grid.DataSource.DataSet.RecNo);
    Grid.Canvas.Brush.Color := RowColors[OddRow];
    Grid.DefaultDrawColumnCell(Rect, DataCol, Column, State);

    // If you want the check box code to only run for a single grid,
    // you can add that check here using something like
    //
    // if (Column.Index = 3) and (Sender = DBGrid1) then
    //
    if (Column.Index = 3) then // 
      CheckBoxDrawColumCell(Sender, Rect, DataCol, Column, State)
  end;
end;

// Checkbox (from yours) - again, notice method name change.
procedure TEditDocket.CheckBoxDrawColumnCell(Sender: TObject; 
  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
 DrawRect: TRect;
 Grid: TDBGrid;
begin
  // Don't use DBGrid1, because it makes the code specific to a single grid.
  // If you need it for that, make sure this code only gets called for that 
  // grid instead in the generic handler; you can then use it for another 
  // grid later (or a different one) without breaking any code
  if column.Index = 3 then
  begin
    Grid := TDBGrid(Sender);
    DrawRect:= Rect;
    Drawrect.Left := Rect.Left + 24;
    InflateRect (DrawRect, -1, -1);
    Grid.Canvas.FillRect (Rect);
    DrawFrameControl (Grid.Canvas.Handle, DrawRect, DFC_BUTTON,
      ISChecked[Column.Field.AsInteger]);  // Don't know what ISChecked is 
   end;

   // The below should no longer be needed, because DefaultDrawColumnCell has
   // been called by the generic handler already.
   //
   // else 
   //  Grid.DefaultDrawColumnCell (Rect, DataCol, Column, State);
end;

在看到您对Sertac的评论之后:

  

在一个网格中,它可以是第3列,而它可以是第4列,需要将其绘制为复选框。

我在上面的代码中提供了一种解决方法(请参阅GenericDrawColumnCell中的注释)。另一种方法(假设每个网格中只有一列需要复选框)是指示包含TDBGrid.Tag属性中的复选框的列:

if (Column.Index = Grid.Tag) then

答案 1 :(得分:1)

独立地,我使用网格的'tag'属性达到了以下答案。

在客户端表单中,我写了

 dbGrid1.OnDrawColumnCell:= dm.DBGrid1DrawColumnCell;
 dbGrid1.tag:= 3;  // column with checkbox
 dbGrid2.OnDrawColumnCell:= dm.DBGrid1DrawColumnCell;
 dbGrid2.tag:= $23;  // both columns 2 and 3 are checkboxes 

默认处理程序现在是

procedure TDm.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
          DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  IsChecked : array[0..1] of Integer =
                (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED);

var
 DrawRect: TRect;
 tag: integer;
 cols: set of byte;

begin
 if sender is TDBGrid then
  begin
   tag:= TDBGrid (sender).tag;
   if (THackDBGrid (sender).DataLink.ActiveRecord + 1 = THackDBGrid (sender).Row)
   or (gdFocused in State) or (gdSelected in State) then
    with TDBGrid (sender) do
     begin
      canvas.Brush.Color:= clMoneyGreen;
      canvas.font.color:= clNavy;
     end;

   cols:= [];
   while tag > 0 do
    begin
     cols:= cols + [tag mod 16];
     tag:= tag div 16
    end;

   if column.Index in cols then
    begin
     DrawRect:= Rect;
     drawrect.left:= rect.left + 24;
     InflateRect (DrawRect, -1, -1);
     TDBGrid (sender).Canvas.FillRect (Rect);
     DrawFrameControl (TDBGrid (sender).Canvas.Handle, DrawRect, DFC_BUTTON,
                   ISChecked[Column.Field.AsInteger]);
    end
   else
    begin
     TDBGrid (sender).DefaultDrawColumnCell (Rect, DataCol, Column, State);
    end;
  end;
end;

这意味着第0列绝不能是复选框。使用集合允许网格中最多四列为复选框。