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.
×