1. Tech

Your suggestion is on its way!

An email with a link to:


was emailed to:

Thanks for sharing About.com with others!

Professional Looking Grids with Custom Drawing
Page 1: How to fix-up the column headers.
 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 2: Adding Buttons and CheckBoxes
• Page 3: Merging Cells

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

Article submitted by Vegar Vikan for the Delphi Programming Quickies Contest - Round #2 Winner!

Using custom drawing to make your grids look as nice as the expensive third party suites. Three main topics are presented: how to fix-up the column headers, how to add clickable buttons and checkboxes inside cells and how to simulate merged cells.

A little knowledge and creativity
There are a lot of grid components out there, all with a long list of advanced features for you to play with. But there are some issues with these grids making them unwanted for private use. First of all, lots of them are data aware. Personally I like to hold my data in objects and streams where I can easily remain control. Secondly, some of them represent a huge overkill of what I usually am in need of. And third, the price... $350 is quite much to pay for a grid when all you do is playing around at the boy's room making shareware for friends.

What I will try to show you here, is that with a little knowledge and creativity, you can turn Delphi's own grids into nice, professional looking grids. There are three main topics that I will show you. First of all we should take a look on how to fix-up the column header. Then I will show how to add clickable buttons and checkboxes inside cells. And last I will show a way to simulate merged cells. Below I have included a screenshot from the sample application that comes with the article, showing some ideas of what you can do with a standard TStringGrid.

About Delphi Programming Custom Drawing: TStringGrid
Doing some header-makeup
Have you ever noticed how the FixedRows-property is set to zero when the number of rows goes below two? That means that you loose the 3D-look, and you want get it back if you add some rows. You manually have to set the FixedRows property back after adding more rows. We will make a two-step solution for this. First we have to make sure the FixedRows property is updated when changing RowCount. Second we have to make sure the header keeps a consistent 3D-look.

I usually have a 'UpdateGrid()'-method that I call after adding or deleting data records. First of all this method updates the RowCount property. Then it checks the FixedRows property, and finally invalidates the grid. As you can see from the code listing, the first step is rather trivial. In a real-world situation I would have read the row count from the data holder, but here I have passed it as a parameter since we don't have any data.

procedure TfrmMain.UpdateGrid(rowCount: integer);
 //Update rowcount
 gridOwnerDraw.RowCount := rowCount;
  //If rowcount 
  if gridOwnerDraw.RowCount > 1 then
    gridOwnerDraw.FixedRows := 1;
  //Invalidate grid

The next step is the drawing and involves some more work. First of all we calculate the position for the text. Then we set all the properties of the canvas object and clear the cell. Next thing we use the DrawText method provided with the Windows API. This method has some very usable flags that we can provide. Take a look at the documentation to get a complete description. Here I have used four flags that give us a single line of text, centered both vertical and horizontal and with an ellipse ('...') at the end if the cell is too small to fit all of the text. At the end of the method, we draw the lines around the cell to simulate a 3D-look.

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;
    if ARow = 0 then
      result := format('Header %d', [ACol])
  txtRect: TRect;
  str: string;
  //If header is to be drawn:
  if ARow = 0 then
    txtRect := Rect;
    txtRect.Left := Rect.Left + TXT_MARG.x;
    txtRect.Top := Rect.Top + TXT_MARG.y;
    //Setting canvas properties and erasing old cellcontent:
    with gridOwnerDraw.Canvas do
      Brush.Color := clBtnFace;
      Font.Style := [];
      Font.Color := clWindowText;
      Font.Name := gridOwnerDraw.Font.Name;
      Font.Size := gridOwnerDraw.Font.Size;
    //Drawing text:
    str := GetText(ACol, ARow);
    DrawText(gridOwnerDraw.canvas.Handle, PChar(str),  
             length(str), txtRect, 
    //Drawing 3D-frame:
    with gridOwnerDraw.Canvas do
      Pen.Style := psSolid;
      Pen.Width := 1;
      Pen.Color := clWhite;
      Polyline([point(rect.left, rect.bottom),
               rect.TopLeft, point(rect.Right, rect.top)]);
      Pen.Color := clBtnShadow;
      Polyline([point(rect.left+1, rect.bottom-1), 
               point(rect.right-1, rect.bottom-1), 
               point(rect.Right-1, rect.Top+1)]);

It is possible to include components for editing inside cells, but if a checkbox or a simple button is all you need you can easily do it with some custom drawing...

Next page > How to add clickable buttons and checkboxes inside cells > Page 1, 2, 3

©2015 About.com. All rights reserved.