如何在TStringGrid.OnDrawCell的单元格外画图?

How to draw outside the cell in TStringGrid.OnDrawCell?

我有一个 TStringGrid,其单元格使用 OnDrawCell 事件获得自定义背景颜色。现在我想在视觉上将每一行扩展到网格的右端 ClientRect,即删除不再有列的空白。

我考虑过使用额外的 "phantom" 列并不断调整它的 ColWidth,但是这种 hack 不适用于网格有点笨拙的垂直滚动行为。我的首选解决方案是简单地绘制该区域。

计算相关的矩形很容易,但是我在上面画的东西会立即被擦除。我禁用了 DefaultDrawing 并删除了所有选项 goFixedVertLinegoFixedHorzLinegoVertLinegoHorzLine,但没有任何效果。

下面是一些示例代码:

LGrid := TStringGrid(Sender);
LGrid.Canvas.Brush.Color := clYellow + 1000 * (1 + ARow);
if ACol = LGrid.ColCount - 1 then
  Rect.Right := LGrid.ClientRect.Right; // Doesn't have any effect
LGrid.Canvas.FillRect(Rect);

实现上述代码意图的最简单方法是什么?我希望可以在不编写插入器 class、覆盖 Paint 方法并使用此事件实现我已经可用的大部分内容的情况下在那里进行绘制。

单元格绘制完成后,VCL会填充单元格未占用的空白区域。这就是你的画被过度绘制的原因。使用 OnDrawCell 事件处理程序可以防止您绘制的内容立即被擦除,无需覆盖 Paint 或派生新控件。

由于VCL使用相同的设备上下文绘制单元格和空白区域,您可以从设备上下文中裁剪掉刚刚绘制的扩展矩形,OS将忽略VCL后面的绘制调用对于那个区域。

LGrid := TStringGrid(Sender);
LGrid.Canvas.Brush.Color := clYellow + 1000 * (1 + ARow);
if ACol = LGrid.ColCount - 1 then
  Rect.Right := LGrid.ClientRect.Right;
LGrid.Canvas.FillRect(Rect);
ExcludeClipRect(LGrid.Canvas.Handle, Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);  // <--