Search code examples
delphidelphi-2010vcl

How to draw outside the cell in TStringGrid.OnDrawCell?


I have a TStringGrid whose cells get a custom background color using the OnDrawCell event. Now I would like to visually extend each row to the right end of the grids ClientRect, i.e. remove the whitespace where there are no columns anymore.

I considered using an additional "phantom" column and constantly adjusting its ColWidth, but that hack doesn't work well with the grids somewhat awkward vertical scrolling behavior. My preferred solution would be to simply paint that area.

Calculating the relevant rect is easy, but what I paint to it gets erased instantly. I disabled DefaultDrawing and removed all of the options goFixedVertLine, goFixedHorzLine, goVertLine and goHorzLine, but to no effect.

Here's some sample code:

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

What is the easiest way to achieve what the code above intended? I hope it is somehow possible to paint there without writing an interposer class, overriding the Paint method and implementing much of what is already available to me using this event.


Solution

  • The VCL fills the empty area not occupied by cells after drawing of the cells are complete. That's why your painting gets over-drawn. It's possible to prevent what you paint getting erased instantly using the OnDrawCell event handler, no need to override Paint or derive a new control.

    Since the VCL uses the same device context for drawing the cells and the empty area, you can clip out the extension rectangle you just drew from the device context, and the OS will disregard VCL's later painting calls for that zone.

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