Custom Report Components Writing
FastReport has a great number of components, which can be placed on a report design page. They are: text, picture, line, geometrical figure, OLE, Rich, bar code, diagram etc. You can also write your own custom component, and then attach it to FastReport.
In FastReport several classes are defined, from which components are inherited. For more details, see “FastReport Classes Hierarchy” chapter. The TfrxView
class is of primary interest to us, since most report components are inherited from it.
One should have at least the Draw
method defined in the TfrxReportComponent
basic class.
procedure Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended); virtual;
This method is called when component is painted in designer, in preview window, and during output printing. TfrxView
overrides this method for drawing object frame and background. This method should draw component contents on “Canvas” drawing surface. Object coordinates and sizes are stored in AbsLeft
, AbsTop
, Width
and Height
properties accordingly.
ScaleX and ScaleY parameters define object scaling in X-axis and Y-axis respectively. These parameters are equal 1 at 100% zoom and can vary, if user modifies zooming either in designer or in preview window. OffsetX and OffsetY parameters point shifting by X-axis and Y-axis. Thus, when taking these parameters into account, the upper left corner coordinate will be as follows:
X := Round(AbsLeft * ScaleX + OffsetX);
To simplify operations with coordinates, BeginDraw
method (which has parameters similar to Draw
method) is defined in TfrxView
class
procedure BeginDraw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended); virtual;
It should be called in the first line of Draw
method. This method performs coordinates transformation into FX
, FY
, FX1
, FY1
, FDX
, FDY
, FFrameWidth
integer values, which can be later used in TCanvas methods. This method also copies Canvas, ScaleX, and ScaleY values into FCanvas
, FScaleX
, FScaleY
variables to which one can refer from any class method.
There are also two methods for drawing backgrounds for and frames of objects in TfrxView
class.
procedure DrawBackground;
procedure DrawFrame;
BeginDraw
method should be called before calling these methods.
Let us examine creating a component which will display an arrow.
type
TfrxArrowView = class(TfrxView)
public
{ we should override only two methods }
procedure Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended); override;
class function GetDescription: String; override;
published
{ Place required properties into the published section }
property BrushStyle;
property Color;
property Frame;
end;
class function TfrxArrowView.GetDescription: String;
begin
{ component description will be displayed next to its icon in toolbar }
Result := 'Arrow object';
end;
procedure TfrxArrowView.Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended);
begin
{ call this method to perform coordinates transformation }
BeginDraw(Canvas, ScaleX, ScaleY, OffsetX, OffsetY);
with Canvas do
begin
{ set colors }
Brush.Color := Color;
Brush.Style := BrushStyle;
Pen.Width := FFrameWidth;
Pen.Color := Frame.Color;
{ draw arrow }
Polygon(
[Point(FX, FY + FDY div 4),
Point(FX + FDX * 38 div 60, FY + FDY div 4),
Point(FX + FDX * 38 div 60, FY),
Point(FX1, FY + FDY div 2),
Point(FX + FDX * 38 div 60, FY1),
Point(FX + FDX * 38 div 60, FY + FDY * 3 div 4),
Point(FX, FY + FDY * 3 div 4)]);
end;
end;
{ registration }
var
Bmp: TBitmap;
initialization
Bmp := TBitmap.Create;
Bmp.LoadFromResourceName(hInstance, 'frxArrowView');
frxObjects.RegisterObject(TfrxArrowView, Bmp);
finalization
{ delete component from list of available ones }
frxObjects.Unregister(TfrxArrowView);
Bmp.Free;
end.
To create a component which displays any data from a DB one should transfer DataSet
, DataField
properties into the “published” section, and then override GetData
method. Let us examine it using the TfrxCheckBoxView
standard component as an example.
This component can be connected to a DB field via the DataSet
and DataField
properties, which are declared in TfrxView
basic class. In addition, this component has the Expression
property, into which an expression can be placed. As soon as it is calculated, result will be placed into Checked
property. This component displays a cross, if Checked
property equals “True.” Below you can see the component’s initial declaration text (its most important parts).
TfrxCheckBoxView = class(TfrxView)
private
FChecked: Boolean;
FExpression: String;
procedure DrawCheck(ARect: TRect);
public
procedure Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended); override;
procedure GetData; override;
published
property Checked: Boolean read FChecked write FChecked default True;
property DataField;
property DataSet;
property Expression: String read FExpression write FExpression;
end;
procedure TfrxCheckBoxView.Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended);
begin
BeginDraw(Canvas, ScaleX, ScaleY, OffsetX, OffsetY);
DrawBackground;
DrawCheck(Rect(FX, FY, FX1, FY1));
DrawFrame;
end;
procedure TfrxCheckBoxView.GetData;
begin
inherited;
if IsDataField then
FChecked := DataSet.Value[DataField]
else if FExpression <> '' then
FChecked := Report.Calc(FExpression);
end;