Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bold StringGrid Gridlines?

1,003 views
Skip to first unread message

Ben Crain

unread,
Sep 13, 1999, 3:00:00 AM9/13/99
to
Thinking of my StringGrid as a matrix containing various submatrices, I
would like to highlight certain submatrices by making the gridlines that
define their borders bold in appearance, while leaving gridlines
internal to a submatrix in their present, rather grayed-out
appearance. Alternatively, I might want to make the internal gridlines
invisible, leaving those on submatrix borders visible. I think I would
prefer the first alternative, but would like to try both. I cannot,
however, find a way to do either. Advice greatly appreciated...

Ben Crain

Rick Rogers (TeamB)

unread,
Sep 13, 1999, 3:00:00 AM9/13/99
to
> by making the gridlines that define their borders bold in appearance

The gridlines aren't very flexible, but you can turn them off and draw
anything you want into the cell, by using the OnDrawCell event. First, set
the GrideLineWidth property to zero, then provide this sort of
OnDrawCellEvent handler:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids;

type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
public
function InMatrix(ACol, ARow: Integer): Boolean;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

function TForm1.InMatrix(ACol, ARow: Integer): Boolean;
begin
Result := (ACol > 1) and (ACol < 4) and (ARow > 1) and (ARow < 4);
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if InMatrix(ACol, ARow) then
begin
with StringGrid1.Canvas do
begin
Pen.Color := clBlue;
Pen.Width := 1;
Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
end;
end;
end;

end.

Lukas Hazlehurst

unread,
Sep 14, 1999, 3:00:00 AM9/14/99
to
Not a direct solution, but OnDrawCell allows you to change colours of
columns and if you adjust the width of the relevant columns this provides an
effective highlighting of critical info.

Cheers Derham McAven

Rick Rogers (TeamB)

unread,
Sep 18, 1999, 3:00:00 AM9/18/99
to
> I failed to make clear that the submatrices I want to highlight will in
> general, contain more than one cell

No, that was clear, but I was expecting you to extrapolate from the example
:).

> So I don't want to draw rectangles around single cells, but around
> submatrices containing several cells

So implement this logic in your OnDrawCell event handler. You'll need a way
to determine for any particular cell which combination of edges (top, left,
bottom, right) need to be drawn. You can obtain this information from your
submatrix data structure, and then use MoveTo and LineTo to draw lines only
on the necessary edges.

>The code above obliterates what's in the cells

See below.

> A further curiosity: the DrawCell event also produces a continual
> "flickering" of the StringGrid

The flickering and obliteration are caused by the combination of
DefaultDrawing set to True, and using Canvas.Rectangle.

With DefaultDrawing = True, the Delphi grid component draws the cell, and
then fires your OnDrawCell event. The string grid will draw the text into
the cell. The Rectangle method draws a rectangle, but also fills in the
interior of the rectangle in the brush color. This overwrites the text drawn
by the grid -- hence flicker and obliteration.

Either a) don't overwrite the contents of the cell drawn by the grid, or b)
set DefaultDrawing to False and do all of your own drawing, including
drawing the text with Canvas.TextRect.

This example doesn't overwrite the grid cell contents, so you won't see
flicker nor will you need to use TextRect:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

Grids, Buttons;

type

TForm1 = class(TForm)
StringGrid1: TStringGrid;
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);

private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

type
TCellEdge = (ceLeft, ceTop, ceRight, ceBottom);
TCellEdges = set of TCellEdge;

function GetEdges(ACol, ARow: Integer): TCellEdges;
begin
Result := [];
{ Hard-coded simulated matrix data }
{ Replace with intelligent algorithm based on your submatrix structure }
if (ACol = 1) and (ARow = 1) then Result := [ceLeft, ceTop]
else if (ACol = 1) and (ARow = 3) then Result := [ceLeft, ceBottom]
else if (ACol = 3) and (ARow = 1) then Result := [ceRight, ceTop]
else if (ACol = 3) and (ARow = 3) then Result := [ceRight, ceBottom]
else if (ACol = 1) and (ARow = 2) then Result := [ceLeft]
else if (ACol = 3) and (ARow = 2) then Result := [ceRight]
else if (ARow = 1) and (ACol = 2) then Result := [ceTop]
else if (ARow = 3) and (ACol = 2) then Result := [ceBottom];
end;

procedure DrawEdges(Canvas: TCanvas; ARect: TRect; Edges: TCellEdges;
AColor: TColor; AWidth: Integer);
begin
with Canvas do
begin
Pen.Color := AColor;
Pen.Width := AWidth;
if ceLeft in Edges then
begin
MoveTo(ARect.Left, ARect.Top);
LineTo(ARect.Left, ARect.Bottom + 1);
end;
if ceRight in Edges then
begin
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
end;
if ceTop in Edges then
begin
MoveTo(ARect.Left, ARect.Top);
LineTo(ARect.Right , ARect.Top);
end;
if ceBottom in Edges then
begin
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right , ARect.Bottom - 1);
end;
end;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);

var
Edges: TCellEdges;
begin
Edges := GetEdges(ACol, ARow);
DrawEdges(StringGrid1.Canvas, Rect, Edges, clBlack, 1);
end;

end.

- Rick

0 new messages