Search Results for

    Show / Hide Table of Contents

    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;
    
    Back to top © 1998-2022 Copyright Fast Reports Inc.