Добавление флажка в сетку, чей обработчик OnDrawColumnCell является универсальным

Следуя этому вопросу и это очень полезный ответ: я реализовал вариант ответа Кена в своем большом проекте, где у меня был похожий код, появляющийся во многих формах. Но я заметил, что у меня также были некоторые формы с обработчиками 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, приведенный выше код не выполнялся бы)? Как мне передать такой параметр обработчику?


person No'am Newman    schedule 28.02.2014    source источник
comment
Можно ли определить общий обработчик с дополнительным параметром? Нет, потому что общий обработчик должен соответствовать определению обработчика TDrawColumnCellEvent.   -  person Ken White    schedule 28.02.2014
comment
@KenWhite: Возможно, я мог бы использовать приведенный выше код, а затем вызвать ваш код с подходящими параметрами, чтобы правильно установить фон. Но как я могу обобщить код флажка?   -  person No'am Newman    schedule 28.02.2014
comment
Я не уверен, что вы спрашиваете. Вы имеете в виду, что после того, как я сделал код внутри оператора if, могу ли я впоследствии вызвать более общий обработчик OnDrawColumnCell?? Или вы спрашиваете, независимо от того, выполняется ли оператор if или нет, могу ли я также вызвать более общий обработчик OnDrawColumCell ??   -  person Ken White    schedule 28.02.2014
comment
@KenWhite: общий обработчик OnDrawColumnCell обрабатывает цвет фона для ячейки. Как я могу расширить это, чтобы создать обработчик, который также будет рисовать флажки, когда они нужны? Между прочим, общий код должен вызываться до кода флажка, а не после.   -  person No'am Newman    schedule 28.02.2014
comment
У вас уже есть индекс столбца, не так ли?   -  person Sertac Akyuz    schedule 28.02.2014
comment
@SertacAkyuz: в одной сетке это может быть столбец 3, тогда как это может быть столбец 4, который нужно нарисовать как флажок.   -  person No'am Newman    schedule 28.02.2014
comment
@No'am - Хорошо, тогда вам не нужен «индекс столбца», вам нужна переменная «ColumnWithCheckbox». Попробуйте интегрировать его с сеткой, скажем, свойство «тег», а затем извлеките его из «Отправителя». Конечно, вы можете создать свою собственную сетку. В противном случае вы можете использовать глобальную переменную.   -  person Sertac Akyuz    schedule 28.02.2014
comment
@SertacAkyuz: Именно к такому выводу я пришел. Я представляю свой код в качестве ответа.   -  person No'am Newman    schedule 28.02.2014


Ответы (2)


Я вижу (из цепочки комментариев), что вы хотите вызвать либо общий, либо (в некоторых случаях) также вызвать код для рисования флажка.

общий обработчик OnDrawColumnCell обрабатывает цвет фона для ячейки. Как я могу расширить это, чтобы создать обработчик, который также будет рисовать флажки, когда они необходимы? Между прочим, общий код должен вызываться перед кодом флажка, а не после.

Это на самом деле довольно просто. Определите оба метода с правильной подписью (общий и флажок) (код не проверен!). Однако подключайте общее событие только к событиям 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;

Увидев этот комментарий, который вы написали Сертаку:

в одной сетке это может быть столбец 3, тогда как это может быть столбец 4, который нужно нарисовать как флажок.

Я предложил один из способов решить эту проблему в своем коде выше (см. комментарий в GenericDrawColumnCell). Альтернативой (при условии, что у вас есть только один столбец в каждой сетке, которому нужен флажок) является указание столбца, содержащего флажок, в свойстве TDBGrid.Tag:

if (Column.Index = Grid.Tag) then
person Ken White    schedule 28.02.2014
comment
Я сам пришел к решению «тег» до того, как вы отредактировали свой ответ. Спасибо. - person No'am Newman; 28.02.2014

Независимо от этого я получил следующий ответ, используя свойство сетки «тег».

В клиентской форме я пишу

 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 никогда не должен быть флажком. Использование набора позволяет установить до четырех столбцов в сетке в качестве флажков.

person No'am Newman    schedule 28.02.2014