Delphi 如何在TStringGrid.OnDrawCell中绘制单元格外部?

Delphi 如何在TStringGrid.OnDrawCell中绘制单元格外部?,delphi,delphi-2010,vcl,Delphi,Delphi 2010,Vcl,我有一个TStringGrid,其单元格使用OnDrawCell事件获得自定义背景色。现在,我想直观地将每一行扩展到网格的右端ClientRect,即删除不再有列的空白 我考虑过使用一个额外的“幻影”列,并不断调整其ColWidth,但这种方法在网格的垂直滚动行为中效果不佳。我更喜欢的解决方案是简单地画那个区域 计算相关的rect很容易,但是我画的内容会立即被删除。我禁用了DefaultDrawing并删除了所有选项goFixedVertLine、goFixedHorzLine、goVertLi

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

我考虑过使用一个额外的“幻影”列,并不断调整其
ColWidth
,但这种方法在网格的垂直滚动行为中效果不佳。我更喜欢的解决方案是简单地画那个区域

计算相关的rect很容易,但是我画的内容会立即被删除。我禁用了
DefaultDrawing
并删除了所有选项
goFixedVertLine
goFixedHorzLine
goVertLine
goHorzLine
,但没有任何效果

下面是一些示例代码:

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);

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

单元格绘制完成后,VCL将填充单元格未占用的空白区域。这就是为什么你的画画被画过头了。使用
OnDrawCell
事件处理程序可以防止绘制的内容立即被擦除,无需重写
paint
或派生新控件

由于VCL使用相同的设备上下文来绘制单元格和空白区域,因此您可以剪裁刚刚从设备上下文绘制的扩展矩形,操作系统将忽略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);  // <--
LGrid:=TStringGrid(发送方);
LGrid.Canvas.Brush.Color:=clYellow+1000*(1+ARow);
如果ACol=LGrid.ColCount-1,则
Rect.Right:=LGrid.ClientRect.Right;
LGrid.Canvas.FillRect(Rect);

ExcludeClipRect(LGrid.Canvas.Handle,Rect.Left,Rect.Top,Rect.Right,Rect.Bottom);//虽然
ExcludeClipRect
确实阻止了该区域被擦除-我学到了一些东西:)-不幸的是,总体结果并不像我希望的那样。更改选择或调整大小时,我现在可以成功绘制到的区域不会重新绘制。也许在更多的情况下。不过,不确定解决这个问题是否在这个问题的范围内。@Thijs-OnDrawCell在调整大小(扩大空白区域)时可能不会被调用。在这种情况下,我认为不可能控制对OnDrawCell的干预。我猜不出为什么选择不起作用……要强制重新绘制,可以使用
OnResize
OnSelectCell
OnTopLeftChanged
事件手动
Invalidate()
整个网格,或者只
Invalidate()
所需的部分。