Search code examples
delphigraphicsdrawvcl

How can i get real ClientRect from TGridPanel's cell when it have large BorderWidth?


I'm trying to draw in each cell of a TGridPanel overriding the Paint event. I get the Rect for each cell through CellRect [Row, Col]. This works until an edge is reported. In this case, even the design in designtime is wrong: the 'ClientRect' of the cells do not correspond to the return of CellRect.

I tried to adjust the rect obtained from CellRect, but it is very complex to consider the displacement rate for each. In the image below, I have a TGripanel with a 3px border and each panel with AlignwithMargins = true, all Margins = 3px.

Has anyone ever experienced this?

Native Paint: BorderWidth = 3 BorderStyle = bsNone (each panel is align = alclient and AlignWithMargins = True

native image

My code to get cells 'ClientRect':

procedure TMyCustomGridPanel.paint;
var
  Row, Col: Integer;
  rctCell: TRect;

  function GetColor(C, R: Integer): TColor;
  begin
    if odd(C + R) then
      Result:= clblack
    else
      Result:= clWhite;
  end;
begin
  inherited;

 for Row := 0 to RowCollection.Count -1 do
  begin
    for Col := 0 to ColumnCollection.Count -1 do
    begin
      Canvas.Brush.Color := GetColor(Col, Row);
      if Canvas.Brush.Color <> clDefault then
      begin
        rctCell := CellRect[Col, Row];

        {$REGION 'Adjust first col an row'}
        if Col = 0 then
          rctCell.SetLocation(rctCell.Location.X + BorderWidth, rctCell.Location.Y);

        if Row = 0 then
          rctCell.SetLocation(rctCell.Location.X, rctCell.Location.Y + BorderWidth);
        {$ENDREGION}

        {$REGION 'ajust last cells'}
        if Col = (ColumnCollection.Count -1) then
        begin
          if Col > 0 then // tem mais de uma coluna
            rctCell.SetLocation(rctCell.Location.X - BorderWidth, rctCell.Location.Y);
          rctCell.Right := ClientRect.Right;
        end;

        if Row = (RowCollection.Count -1) then
        begin
          if Row > 0 then
            rctCell.SetLocation(rctCell.Location.X, rctCell.Location.Y - BorderWidth);
          rctCell.Bottom := ClientRect.Bottom;
        end;

        {$ENDREGION}
        Canvas.Pen.Style := psClear;
        Canvas.FillRect(rctCell);
      end;
    end;
  end;

end;

Result with my code: (the panels are just to show that CellRect is not the 'ClientRect' to put a control)

GridPanel
BorderWidth = 10
BorderStyle = bsNone
Color = clmarron

Panels
Align = alClient
Color = clgray
AlignWithMargins = true

enter image description here


Solution

  • Design time rendering of the cell borders (the dotted lines) of a TGridPanel does not take into account the borders of the panel. Thus they do not visually coincide with components you have placed in the grid cells. This is most apparent e.g. with panels of which the Align property is set to alClient.

    To know the actual rectangle of a cell, in coordinates of the TGridPanel, you can use OffsetRect to adjust for the border widths.

    var
      row, col: integer;
      r: TRect;
    begin
      ...
      r := CellRect[Col, Row];
      OffsetRect(r, BorderWidth, BorderWidth);