#1 Re: PDF Engine » Beginner questions about making a text box ((Multiline)TextRect?) » 2018-06-08 13:47:18

Sorry to bother again, but I still cannot get it to work. I managed to get the justified text right but the outcome looks like this:

j6L7F1z.jpg.

It seems as if the drawtext using the justified method somehow doubles the text output on the canvas. One of the texts is completely normal (with two #13#10's before) but the second text (don't know why its appearing) is repeating itself on the first line and some kind of gibberish appears there which I don't want.

I hope I'm not turning to the forums with an OT problem. Personally I am suspicious about the DrawTextJustified line where there is both pdf.VCLCanvas and rect1 in the same brackets and they might be somehow controversial. Maybe it's because there is the programs original rectangle code used but the pdf.VCLCanvas is from another library.

I also created a small "debug" line, which assures me, that the problem must be in that line.

Here is the full code:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, ShellAPI, System.Types,
  Vcl.ComCtrls;

type
    TForm2 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    //procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

uses synPDF, JustifiedDrawText;

var
  filename: string;
  pdf: TPdfDocumentGDI;
  tpdf : TPdfDocument;
  page: TPdfPage;


procedure TForm2.Button1Click(Sender: TObject);
      var
      lText: string;
      rect1: TRect;

const
  // if you need a finer canvas resolution, use a factor to multiply with
  Factor = 2;
  Resolution = 72 * Factor;
  OneMM = Resolution / 25.4; // = 1 mm

begin
  filename := ExtractFilePath(ParamStr(0)) + 'example.pdf';

  pdf := TPdfDocumentGDI.Create();
  try
    pdf.ScreenLogPixels := Resolution;
    page := pdf.AddPage;

    with pdf.VCLCanvas do begin
      Font.Name := 'Times';
      Font.Size := 14 * Factor;

      TextOut((pdf.VCLCanvasSize.cx - TextWidth(Edit1.Text)) div 2, Round(20 * OneMM), Edit1.Text);

      with Rect1 do begin
        Left   := Round(20 * OneMM);
        Top    := Round(22 * OneMM + TextHeight(Edit1.Text));
        Right  := pdf.VCLCanvasSize.cx - Round(20 * OneMM);
        Bottom := pdf.VCLCanvasSize.cy - Round(20 * OneMM);
      end;


      Font.Size := 12 * Factor;
      lText := Memo1.Text;

      DrawTextJustified( pdf.VCLCanvas,  #13#10+#13#10+(lText), rect1,  []); // The problem lies somewhere here


//      DrawText(Handle, AnsiString(lText), Length(lText),
//               Rect1, DT_Center or DT_WORDBREAK); Text

     end;

    pdf.SaveToFile(filename);
    Shellexecute(Handle, 'open', PChar(filename), '', '', SW_Normal);


        //Debugger
        Application.Initialize;
        Application.CreateForm(TForm2, Form2);
        AllocConsole;
        writeln(lText);
        Application.Run;

  finally
    pdf.Free;
  end;
end;

end.

all the best
Oliver

#2 Re: PDF Engine » Beginner questions about making a text box ((Multiline)TextRect?) » 2018-06-07 15:33:43

Thanks! I got both of your suggestions to work after some small changes:

The one in your first post:

 DrawText(Handle, AnsiString(lText), Length(lText),
               Rect1, DT_Center or DT_WORDBREAK); Text 

The one in your second post:
     

lText := Memo1.Lines.Text;  // because the 2nd arg is var Text: string
 TextRect(Rect1, lText, [tfBottom, tfWordBreak]); 

My next question is, that is there any way to make the text justified? Values like DT_JUSTIFIED of tfJUSTIFIED sadly don't exist and I'm unsure, that if I used some other libraries (like mORMotReport) to stylize the text the whole thing would work.

#3 Re: PDF Engine » Beginner questions about making a text box ((Multiline)TextRect?) » 2018-06-07 09:15:19

Thank you very much for your reply. This code works good although I have a small problem with it (maybe it's the compilers fault, I'm using Rad Studio).

The input text of Memo1 doesn't appear correctly in the .pdf file, instead it consists of random symbols and it also displays a error by Acrobat reader. Do you have any idea about that?

IgL4RpZ.jpg

all the best
Oliver

#4 mORMot 1 » Problem with Reports WordWrap on columns » 2018-06-06 22:32:25

oliver
Replies: 0

I have a small problem that hopefully someone knows a solution to.

I need to have two columns of text and I need them both wrapped. Also I need the right columns text to be always on the same line with the lowest left columns line therefore I used a piece of code, that always adds enough slinebreaks before the text of right column.

I used WordWrapLeftCols := true; but it seems to only activate on the left column, because if you look at pic2, there is a square-like symbol instead of a empty line.

pic1: only with one line in left column
J9DbLEz.jpg


pic2: two lines in left column but left column didn't go downwards - only got the square symbol.
FOeKyg2.jpg

All the best
Oliver

#5 PDF Engine » Beginner questions about making a text box ((Multiline)TextRect?) » 2018-06-05 23:32:07

oliver
Replies: 7

Hello

I'm trying to create a program, that basically allows the user just to fill in the blanks and receive a fully formatted .pdf file. The program I've done is much longer but I made a shortened version to illustrate the biggest problem this far.

Basically I want to create a text box with certain size and position that draws the text of TMemo.text and continues the same text on a new line whenever the length of the input text reaches its set limit. Also the whole text would be justified inside the given area.

I searched the whole forum for examples and I've tried MultilineTextRect and some other alternatives but sadly unsuccessfully. Since I'm a beginner then I would be extremely glad, if anyone could be of any help on my search for the solution.

The code part is here:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, ShellAPI;

type
  TForm2 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

uses synPDF;

var filename : string;
    pdf  :TPdfDocumentGDI;
    page :TPdfPage;
    Rect1 :TRect;

procedure TForm2.Button1Click(Sender: TObject);  //Clicking the button saves all the formatted text to example.pdf file in the programs directory and opens the same pdf file automatically

begin
  filename := extractfilepath(paramstr(0))+'example.pdf';
  pdf.Canvas.BeginText;
  Rect1 := TRect.Create(20,20,30,16); // I don't even know, if the rectangle is needed here, because the parameters don't seem to change the outcome of the text in any way.
  pdf.VCLCanvas.Font.Name := 'Times';
  pdf.VCLCanvas.Font.Size := 14;
  pdf.VCLCanvas.TextHeight(Edit1.Text);
  pdf.VCLCanvas.TextWidth(Edit1.Text);
  pdf.VCLCanvas.FrameRect(Rect1);
  pdf.VCLCanvas.TextRect(Rect1, ((page.PageWidth - pdf.VCLCanvas.TextWidth(Edit1.Text)) div 2), 250, Edit1.Text);  // A solution the title can always stay in the middle of the page.

  pdf.VCLCanvas.TextRect(Rect1, 48 , 300, Memo1.Text); // THE BIGGEST QUESTION - This is the text I want to be in a certain box with certain text alignment etc. ~2 cm from the left edge of page.

  pdf.Canvas.EndText;
  try
    pdf.SaveToFile(filename);
  finally pdf.Free;
    Shellexecute(Handle,'open',pchar(filename),'','', SW_Normal);
  end;
end;


procedure TForm2.FormCreate(Sender: TObject); 
begin
  pdf:=TPdfDocumentGDI.Create();
  filename := extractfilepath(paramstr(0))+'test.pdf';
  pdf.ScreenLogPixels   := 72;
  page := pdf.AddPage;
  page.PageLandscape := false;
  pdf.DefaultPaperSize := psA4;
end;

end. 

I thought that maybe one and also a quite simple-minded solution to the problem would be something like this, but I couldn't even finish this ones "else section". Basically the logical operation would draw the text, if it was short enough (until the 48 pixels from the left edge of the paper) or else detect the nearest spacebar before the edge of the box and then the program starts a new line from that place. Also the text would be justified, so the left edge looks straight.

if pdf.VCLCanvas.TextWidth(Memo1.Text) < page.PageWidth-48
  then
  pdf.VCLCanvas.TextRect(Rect2, 48 , 300, Memo1.Text)

  else
  pdf.VCLCanvas.TextRect(Rect2, 48 , 300, wraptext(Memo1.Text, #13#10, ['a'], 10));

The .pdf outcome at the moment is like this. The title is where it should be, but the text goes far over the edge: https://ufile.io/ydqmo
The .zip file with all the Delphi Pascal files can be found on the following link: https://ufile.io/yj59n
Just open Project3.dproj and you see the whole program.

I'm pretty sure that I have more questions coming up but I need to solve this problem first. When I get the thing ready I can upload it here also, so people could have an example.

All the best
Oliver

Board footer

Powered by FluxBB