在 TStringGrid 的单元格中的按钮上绘制和图像

Drawing and image on a button in a cell in a TStringGrid

我在 Lazarus 中有一个 TStringGrid,运行 在 Linux 中。我有一个编辑器类型为 cbsButton 的专栏。我希望按钮显示特定图像,而不是省略号。我有以下代码,它会导致错误:

procedure TForm1.streams_gridDrawCell(Sender: TObject; aCol, aRow: Integer; aRect: TRect; aState: TGridDrawState);
var
    aCanvas: TCanvas;
    aGrid: TStringGrid;
    Editor: TWinControl;
    image: TImage;
begin
    if (aCol <> 1) or (aRow = 0) then begin
        Exit;
    end;

    aGrid := (Sender as TStringGrid);

    aCanvas := image.Canvas;
    aCanvas.FillRect(aRect);
    imagelist1.Draw(aCanvas, aRect.Left+2, aRect.Top+2, 8);

    Editor := (aGrid.EditorByStyle(cbsButton) as TButtonCellEditor);
    Editor.Brush.Style := TBrushStyle.bsImage;
    (Editor.Brush.Image as TImage) := image; // causes the error below
end;

错误是:

mainform.pas(156,23) Error: Class or Object types "TFPCustomImage" and "TImage" are not related

在这一点上,我确定我正在以完全错误的方式处理这件事。有人可以让我回到正确的道路上吗?

Editor.Brush.Image 是类型 TFPCustomImage 的 属性。这是一个 TPersistent 后代。 TImageTCustomImage 的后代,因此 TGraphicControlTControl。所以这些完全不同 类 不兼容。

因此您不需要转换 (Editor.Brush.Image as TImage) 并将任何 TImage 实例分配给它。

我怀疑 OnDrawCell 事件是修改单元格编辑器的正确位置,因为在绘制单元格时可能此时不存在正确的单元格编辑器。

定义单元格编辑器的正确事件是网格的OnSelectEditor 事件。请阅读 wiki (http://wiki.lazarus.freepascal.org/Grids_Reference_Page)。

您使用的cbsButton编辑器继承自TButton。 TButton 没有字形 属性 - 您不能将位图分配给按钮。但是你是否可以轻松编写自己的单元格编辑器,只需按照 examples/gridexamples/gridcelleditor:

中的标准示例即可
  • 在表单中添加一个 TBitBtn。删除它的标题,将请求的图像添加到字形 属性。将可见 属性 设置为 false。
  • 在此按钮的 OnClick 事件中写入您希望如何编辑单元格。访问由网格的属性 Col 和 Row 指定的单元格。例如,我假设您只想打开一个 InputBox:
    procedure TForm1.BitBtn1Click(Sender: TObject);
    begin
      StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := 
        InputBox('Input some text', 'Text:', '');
    end;
  • 现在为网格的OnSelectEditor 事件编写事件处理程序。它必须将 BitBtn 分配给事件的 Editor 参数,并确保按钮位于所选单元格内的正确位置 - 仅此而已!
    procedure TForm1.StringGrid1SelectEditor(Sender: TObject; aCol, aRow: Integer;
      var Editor: TWinControl);
    var
      R: TRect;
    begin
      if (aCol=2) and (aRow > 0) then begin
        R := StringGrid1.CellRect(aCol, ARow);
        R.Left := R.Right - (R.Bottom - R.Top);
        BitBtn1.BoundsRect := R;
        Editor := BitBtn1;
      end;
    end;