1. Computing & Technology
Professional Looking Grids with Custom Drawing
Page 3: How to simulate merged cells (sub headings).
 Win prizes by sharing code!
Do you have some Delphi code you want to share? Are you interested in winning a prize for your work?
Delphi Programming Quickies Contest
 More of this Feature
• Page 1: Fixing Column Headers
• Page 2: Adding Buttons and CheckBoxes

• Download Sample Project
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Get Crazy - Draw Yourself
• Custom Draw Menus
• Graphical Combos
• Custom shaped forms and controls

Merged cells
In the sample code, I have made a subheading for each third data row. When I need to present data grouped into subcategories, I often want the subheadings to flow across cell boundaries. One solution for this to happen is to merge all the columns into one wide cell. The way I have found to this is shown in the last listing.

About Delphi Programming Custom Drawing: TStringGrid

As you will see that's no hard at all. Before we start to draw, we modify our cell Rect to include the complete width of the grid. This will result in a fixed sub header, unaffected by horizontal scrolling. Using the same approach to merge any two columns is not that hard. Use GetCellRect( ) method of the grid to get the boundaries for the first and the last you want to merge. Then calculate the merged cell Rect from them.

procedure TfrmMain.gridOwnerDrawDrawCell
  (Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
  //Make some text to display in cell:
  function GetText(ACol, ARow: integer): string;
  begin
    [...]
  end;
var
  txtRect: TRect;
  btnRect: TRect;
  btnState: integer;
  tmpstr, str: string;
  kodewidth: integer;
  tmpRect: TRect;
  focusRect: TRect;
begin
  //If header is to be drawn:
  if ARow = 0 then
  begin
    [...]
  end
  //If subheader is to be drawn:
  else if ARow mod 4 = 1 then
  begin
    //Merging cell:
    rect.right := gridOwnerDraw.width;
    rect.Left := 0;

    //Setting canvas properties and erasing old cellcontent:
    gridOwnerDraw.Canvas.Brush.Color := clWindow;
    gridOwnerDraw.Canvas.Brush.Style := bsSolid;
    gridOwnerDraw.Canvas.Pen.Style := psClear;
    gridOwnerDraw.Canvas.FillRect(rect);

    //Textposition:
    txtRect := Rect;
    txtRect.Left := Rect.left + TXT_MARG.x;

    //Drawing text:
    str := GetText(ACol, ARow);
    gridOwnerDraw.Canvas.Font.Color := clInfoText; //clHighlightText;
    gridOwnerDraw.Canvas.Font.Name := gridOwnerDraw.Font.Name;
    gridOwnerDraw.Canvas.Font.Size := gridOwnerDraw.Font.Size;
    gridOwnerDraw.Canvas.Font.Style := [fsBold];
    DrawText(gridOwnerDraw.canvas.Handle, PChar(str), 
             length(str), txtRect, DT_SINGLELINE or DT_LEFT or 
             DT_VCENTER or DT_END_ELLIPSIS);

    //Drawing focusrect:
    if gdSelected in State then
    with gridOwnerDraw.canvas do begin
      Pen.Style := psInsideFrame;
      Pen.Color := clBtnShadow;
      Polyline([Point(Rect.left, Rect.Top), 
                Point(Rect.right-1, Rect.Top)]);
      Polyline([Point(Rect.left, Rect.Bottom-1), 
                Point(Rect.right-1, Rect.Bottom-1)]);
      if ACol = 0 then
        Polyline([Point(Rect.left, Rect.Top), 
                  Point(Rect.left, Rect.Bottom-1)])
      else if ACol = gridOwnerDraw.ColCount - 1 then
        Polyline([Point(Rect.right-1, Rect.Top), 
                  Point(Rect.right-1, Rect.Bottom-1)]);
    end
    else
    begin
      //If not selected, draw a line under subheading:
      gridOwnerDraw.Canvas.Pen.Style := psInsideFrame;
      gridOwnerDraw.Canvas.Pen.Color := clBlack;

      gridOwnerDraw.Canvas.Polyline
                ([Point(rect.Left + TXT_MARG.x, rect.bottom-1), 
                 Point(rect.right, rect.bottom-1)]);
    end
  end
  //For the rest of the rows:
  else
  begin
    [...]
  end;
end;

The goal for this article was to give some hints on how you can make the standard grids form Delphi look good. We have seen that all it takes is some creativity and some playing with the grids canvas. Combining this with a well designed data structure containing your data, you can have a professional look without spending all your money on third-party components suite. I have used a TDrawGrid to present data into hierarchical lists, grouped lists (as shown here) and even nested grids. Download the sample application, and see if this is something that you can use.

That's it
Please download the sample project, and of course post any questions to the Delphi Programming Forum.

First page > How to fix-up the column headers > Page 1, 2, 3

Discuss in my forum

©2012 About.com. All rights reserved.

A part of The New York Times Company.