TAdvStringGrid
Example 72 : Using the ICellGraphic interface for cells
Interfaces are a powerful way to remove code
dependencies and as a result allow to better tailer code size to feature use. In
TAdvStringGrid it is possible to add an interfaced object to a cell and have the
interface paint the cell. This way, all kinds of small or large code can be used
to paint a cell without forcing any user who is not interested in a particular
graphical feature in the grid to link the code.
To achieve this, the interface ICellGraphic was created. This interface currently has only four methods:
ICellGraphic = Interface procedure Draw(Canvas: TCanvas;R: TRect; Col,Row: integer; Selected: boolean; Grid: TAdvStringGrid); function CellWidth: integer; function CellHeight: integer; function IsBackground: boolean; end;
The first method Draw() is called to draw the cell Col,Row within rectangle R on the canvas Canvas. An extra parameter Selected indicates the selection state of the cell. Two functions return the desired size of the graphic in the cell. These functions are used for autosizing in the grid to adapt the cell size automatically to the size of the graphic. A function IsBackground is used to inform the grid whether text still needs to be drawn on top of the graphic or not.
To start using this interface, we need to create a class that implements the interface. In this sample, we propose 3 classes that implement the interface: TSimpleGraphicCell, TComplexGradientCell and TImageCell. TSimpleGraphicCell just demonstrates the concept. TComplexGradient & TImageCell allow to use specific GDI+ features in the grid. Note that by implementing the GDI+ features in the interfaced class, TAdvStringGrid remains completely independent of GDI+ code. So, users who prefer not to include a GDI+ dependency can keep using TAdvStringGrid as-is while users who want to exploit the extra GDI+ features can benefit from this now. The TSimpleGraphicCell class code is:
TSimpleGraphicCell = class(TInterfacedPersistent, ICellGraphic) procedure Draw(Canvas: TCanvas;R: TRect; Col,Row: integer; Selected: boolean; Grid: TAdvStringGrid); function CellWidth: integer; function CellHeight: integer; function IsBackground: boolean; end; function TSimpleGraphicCell.CellHeight: integer; begin Result := 0; // by returning zero, this graphic cell has no minimum cell height requirement end; function TSimpleGraphicCell.CellWidth: integer; begin Result := 0; // by returning zero, this graphic cell has no minimum cell width requirement end; procedure TSimpleGraphicCell.Draw(Canvas: TCanvas; R: TRect; Col, Row: integer; Selected: boolean; Grid: TAdvStringGrid); begin Canvas.Pen.Color := clRed; // draw a simple diagonal line in the cell Canvas.Pen.Width := 2; Canvas.MoveTo(R.Left, R.Top); Canvas.LineTo(R.Right, R.Bottom); end; function TSimpleGraphicCell.IsBackground: boolean; begin Result := true; end; To use the interface in a cell, this can be done with the code: var sg:TSimpleGraphicCell; begin sg := TSimpleGraphicCell.Create; AdvStringGrid1.AddInterfacedCell(2,2,sg); end;
We have created two additional interfaced classes that now open up GDI+ capabilities for use in the grid, ie. adding complex diagonal gradients for example or draw antialiased PNG images in cells (this uses TGDIPicture & AdvGDIP, two units available in the TMS VCL UI Pack):
TComplexGradientCell =
class(TInterfacedPersistent, ICellGraphic)
private
FStartColor, FEndColor: TColor;
FGradientMode: TLinearGradientMode;
public
procedure Draw(Canvas: TCanvas;R: TRect; Col,Row: integer; Selected:
boolean; Grid: TAdvStringGrid);
function CellWidth: integer;
function CellHeight: integer;
property StartColor: TColor read FStartColor write FStartColor;
property EndColor: TColor read FEndColor write FEndColor;
property GradientMode: TLinearGradientMode read FGradientMode write
FGradientMode;
end;
TImageCell = class(TInterfacedPersistent, ICellGraphic)
private
FPicture: TGDIPPicture;
procedure SetPicture(const Value: TGDIPPicture);
public
{ Interface }
procedure Draw(Canvas: TCanvas;R: TRect; Col,Row: integer; Selected:
boolean; Grid: TAdvStringGrid);
function CellWidth: integer;
function CellHeight: integer;
constructor Create;
destructor Destroy; override;
property Picture: TGDIPPicture read FPicture write SetPicture;
end;
{ TComplexGradientCell }
function TComplexGradientCell.CellHeight: integer;
begin
Result := 0;
end;
function TComplexGradientCell.CellWidth: integer;
begin
Result := 0;
end;
procedure TComplexGradientCell.Draw(Canvas: TCanvas; R: TRect; Col,
Row: integer; Selected: boolean; Grid: TAdvStringGrid);
var
graphics : TGPGraphics;
linGrBrush: TGPLinearGradientBrush;
begin
// Create GDI+ canvas
graphics := TGPGraphics.Create(Canvas.Handle);
linGrBrush := TGPLinearGradientBrush.Create(MakeRect(r.Left,r.Top,r.Right
- r.Left,r.Bottom - r.Top),ColorToARGB(FStartColor),ColorToARGB(FEndColor),
FGradientMode);
graphics.FillRectangle(linGrBrush, MakeRect(r.Left , r.Top, r.Right -
r.Left , r.Bottom - r.Top));
linGrBrush.Free;
graphics.Free;
end;
function TComplexGradientCell.IsBackground:
boolean;
begin
Result := true;
end;
{ TImageCell }
function TImageCell.CellHeight: integer;
begin
Result := FPicture.Height;
end;
function TImageCell.CellWidth: integer;
begin
Result := FPicture.Width;
end;
constructor TImageCell.Create;
begin
inherited Create;
FPicture := TGDIPPicture.Create;
end;
destructor TImageCell.Destroy;
begin
FPicture.Free;
inherited;
end;
procedure TImageCell.Draw(Canvas: TCanvas; R: TRect; Col, Row: integer;
Selected: boolean; Grid: TAdvStringGrid);
begin
Canvas.Draw(R.Left, R.Top, FPicture);
end;
function TImageCell.IsBackground: boolean;
begin
Result := false;
end;
procedure TImageCell.SetPicture(const Value: TGDIPPicture);
begin
FPicture.Assign(Value);
end;
The use of the TImageCell and TComplexGradientCell is done with following code:
cg := TComplexGradientCell.Create;
cg.StartColor := clBlue;
cg.EndColor := clAqua;
cg.GradientMode := LinearGradientModeHorizontal;
AdvStringGrid1.AddInterfacedCell(1,3,cg);
ig := TImageCell.Create;
ig.Picture.LoadFromFile('.\personal.png');
AdvStringGrid1.AddInterfacedCell(2,4,ig);
Delphi project & source files for downloading included in the main demos distribution for Delphi.
×