Exporting custom component

SuazaelSuazael Poland
edited 1:43PM in FastReport 4.0
Hello.

I have written component based on TfrxCustomMemoView with some additional drawing on it.

Is it possible to export report with this component to PDF?

Currently all components are "printed" on PDF sheet without my drawing.
type
  TMyFRCustomCell = class(TfrxCustomMemoView)
  protected
    FCellText: string;
  public
    procedure Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended); override;
    //  There is some additional text drawn within this method
  end;

procedure TMyFRCustomCell.Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended);
var tmpRect: TRect;
begin
  tmpRect := Rect(FX + FFrameWidth, FY + FFrameWidth, FX1 - FFrameWidth, FY1 - FFrameWidth);
  DrawText(Canvas.Handle, FCellText, -1, tmpRect, DT_SINGLELINE);
  //  There are some more actions taken here. This is just to show what my goal is.
end;

procedure TMyFRCustomCell.Draw works fine with previewing and printing, but the additional text is not exported using TfrxPDFExport (or any other TfrxCustomExportFilter).


Does any one know how to make it work?
I guess I could override AddObject method in TfrxPDFExport, but is there a easier way? Or maybe someone already has solution for this?

Regards
Suazael

Comments

  • edited 1:43PM
    It seems there's no good news for you [img]style_emoticons/<#EMO_DIR#>/sad.gif" style="vertical-align:middle" emoid=":(" border="0" alt="sad.gif" /> Have a look at similar problem with export to PDF[/img] http://www.fast-report.com/en/forum/index....720&hl=size

    Mick
  • edited 1:43PM
    I see two solutions.

    The first one is easy to implement, but certainly not perfect. Every TfrxView component has the Tag property. The PDF export can process components differently regarding a value of this property. I can introduce the PictureTag property to the PDF export and when a TfrxView with Tag=PictureTag, it will be exported as a picture (JPEG picture, to say more precisely).

    The second one is a bit more complex, but exhaustively solves your issue. The exporting process can be implemented as a chain of handler-routines, each of these routines exporting a specific kind of a component. The export will obtain a new method AttachHandler that will allow a developer to extend the export functionality without modifying the export's code. This may look like this:

    function ExportMyMemoView(Obj: TfrxView): Boolean; // returns True if the passed component has been exported
    begin
    if (Obj is TMyMemoView) and ... then ...
    end;

    PDFExport.AttachHandler(ExportMyMemoView);
    Report.Export(PDFExport);

    After that every TfrxView component will be going through ExportMyMemoView that can either export it or just return "False", thus saying the export to pass the TfrxView further along the handlers chain.

    If you're interested in this approach, I can give you a kind of HTML export (it'll appear in FR5) that implements the last approach and if you're familiar with HTML, you can try to write your handler and provide feedback about usability of the approach.
  • SuazaelSuazael Poland
    edited 1:43PM
    Thanks for the reply.

    First approach sounds easy, but I don't know (for now) how to pass a single TfrxView (or it's descendant) as JPEG to TfrxPDFExport without "rebuilding" TfrxPDFExport on my own.

    The second approach looks promising... I would definitely like to see some code for that. HTML export would be a good example and some "training" for me, how the export works (or will work in ver. 5).
    So, if I may ask, please provide some HTML export.
    Thank you

    Best regards
    Suazael
  • edited 1:43PM
    The first approach doesn't require you to modify any code. You just set the Tag property of some component to 12345 in the designer (or programmaticaly) and set the PictureTag of the export to 12345 and then the TfrxView appears as a picture in in a produced pdf. For instance, if you change the Tag property of all components in your report to 12345 then all they will appear as JPEGs in a pdf.

    For the second approach see your private messages: I've sent you a link to the export. Here're some explanations regarding exporting objects. Find in the main module the function that exports rectangles:
    function TfrxHTMLDivExport.ExportRectangle(Obj: TfrxView): Boolean;
    var
      Shape: TfrxShapeView;
    begin
      Result := False;
    
      if Obj is TfrxShapeView then
        Shape := Obj as TfrxShapeView
      else
        Exit;
    
      Result := Shape.Shape in [skRectangle, skRoundRectangle];
    
      if Result then
        with CreateDiv(Obj) do
          if HTML5 and (Shape.Shape = skRoundRectangle) then
            with TfrxCSSStyle.Create do
            begin
              CSS3Style['border-radius'] := GetBorderRadius(Shape.Curve);
              AddCSSClass(LockStyle(This));
            end;
    end;
    
    function GetBorderRadius(Curve: Integer): string;
    begin
      if Curve < 1 then
        Result := GetBorderRadius(2)
      else
        Result := IntToStr(Curve*4) + 'pt'
    end;
    

    This routine is intended to catch all TfrxShapeViews that are either rectangles or rounded rectangles. If the routine is called with a non-rectangle component it just returns False, thus saying to try to find a more applicable handler for the component. Otherwise it creates the DIV tag with CreateDiv and checks whether it's needed and possible to round corners. If a user set HTML5 to True and the TfrxShapeView is skRoundRectangle then it creates a CSS style, sets it CSS3-style named "border-radius" and adds the CSS style to the created DIV tag via the DIV's AddCSSClass method (it adds a new value to its "class" attribute). Note a call to LockStyle: this method adds a CSS style to an internal CSS stylesheet, assigns a name to it (like ".s123") and returns the classname (like "s123").

    Now look at the constructor:
    constructor TfrxHTMLDivExport.Create(AOwner: TComponent);
    begin
      inherited;
      DefaultExt := '.html';
      FGauge := TfrxBoundsGauge.Create;
    
      AttachHandler(ExportAsPicture);
      AttachHandler(ExportGradient);
      AttachHandler(ExportLine);
      AttachHandler(ExportRectangle);
      AttachHandler(ExportPicture);
      AttachHandler(ExportMemo);
      AttachHandler(ExportAllPictures);
      AttachHandler(ExportTaggedView);
    end;
    

    Here you can see a chain of exporting handlers. When a component is going to be exported, it's firstly sent to ExportTaggedView. If ExportTaggedView refuses to export the component, it's sent to ExportAllPictures and so on. At last, if all handlers refuse to export, ExportAsPicture is called and this last handler exports everything as a picture (it may be JPEG, PNG or some other format, depending on settings of the export). Thus you are able to add your own handler: just create an instance of the export in the usual way and then call to AttachHandler: your handler will be placed at the beginning of the chain and will be the first who accepts component from reports (in other words it will have the highest priority).
  • SuazaelSuazael Poland
    edited 1:43PM
    Hello.
    Draeden wrote: »
    The first approach doesn't require you to modify any code. You just set the Tag property of some component to 12345 in the designer (or programmaticaly) and set the PictureTag of the export to 12345 and then the TfrxView appears as a picture in in a produced pdf. For instance, if you change the Tag property of all components in your report to 12345 then all they will appear as JPEGs in a pdf.

    OK, maybe there is some misunderstanding... I can't find anything like PictureTag property (or anything which has similar functionality). I using FR version 4.10.18.
    I think this will be introduced in next version?

    As for the second approach: you are talking about the next version (5?). So for now I'm stuck.

    Any way, thanks for the reply.
    I will find some way to do what I want, and will wait for the next version of FasrReport. Then exporting will be easier (as seen in your posts).

    Best regards
    Suazael
  • edited 1:43PM
    PictureTag is an option that I can introduce if it helps you. The behavior of this option I described above.

    Pieces of code that you see in my previous post are extracted from the HTML export that I sent you: see you private messages. You can find this code in that export.

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.