Page 1 of 2

PrintPreview vs. TMemo (and bug in TPrintPreview)

PostPosted: June 15th, 2003, 8:33 pm
by Johnny_Bit
Hi @ll

I've tried to make print prevew of memo by richedit, but nothing shows on preview.

My question: How make PrintPreview of TMemo including margins, footer and header of page?

Printing a TMemo

PostPosted: June 17th, 2003, 7:02 am
by richardchaven
Code: Select all
NewPage;

Canvas.DrawRect(..., WordWrap);


I'm really tired, but does this help at all?

PostPosted: June 17th, 2003, 2:55 pm
by Johnny_Bit
well, I don't know :-( I've got this code for printing on printer canvas, but i want to change it so it be compatible with PrintPreview:
Code: Select all
procedure TMainForm.PrintFooter(var R: TRect; LineHeight: Integer);
var
  S : String;
begin
  with Printer do begin

    { utwórz łańcuch zawierający numer strony }
    S := Format('Page %d', [PageNumber]);


    { ustal współrzędne prostokąta, którym wyświetlany będzie łańcuch }
    { zawierający numer strony }

    R.Top := PageHeight - (lineHeight * 2);
    R.Bottom := R.Top + lineHeight;


    { wyświetl centrycznie łańcuch zawierający numer strony }
    DrawText(Handle, PChar(S), -1, R, DT_CENTER);

    { podkreśl tekst zawierający numer strony }
    Canvas.MoveTo(0, R.Top - 2);
    Canvas.LineTo(R.Right, R.Top - 2);
  end;
end;

procedure TMainForm.FilePrintClick(Sender: TObject);
var
  I            : Integer;
  LineHeight   : Integer;
  LinesPerPage : Integer;
  LineCount    : Integer;
  R            : TRect;
  S            : string;
begin
  { wyświetl dialog drukowania }
  if PrintDialog.Execute then begin

    { ustal tytuł drukowanego obiektu }
    Printer.Title := 'Scratch - ' + OpenDialog.FileName;

    { ustaw czcionkę drukarkową zgodnie z czcionką Memo }
    Printer.Canvas.Font := Memo.Font;



    { Oblicz wysokość linii - na podstawie rozmiaru czcionki }
    { i rozdzielczości drukarki. Dodaj 40% na odstęp między liniami }

    LineHeight := Abs(
      MulDiv(Printer.Canvas.Font.Size,
      GetDeviceCaps(Printer.Handle, LOGPIXELSY), 72));
    Inc(LineHeight, (LineHeight * 4) div 10);

    { oblicz, ile linii zmieści się na stronie; uwzględnij }
    { trójliniowy margines                                 }

    LinesPerPage := (Printer.PageHeight div lineHeight) - 4;

    { rozpocznij drukowanie w 4. linii, by zostawić miejsce }
    { na nagłówek }
    LineCount := 4;

    { wydrukuj nagłówek }
    Printer.BeginDoc;
    R.Top    := LineHeight;
    R.Left   := 20;
    R.Right  := Printer.PageWidth;
    R.Bottom := LineHeight * 2;
    DrawText(Printer.Handle,
      PChar(OpenDialog.FileName), -1, R, DT_CENTER);

    { drukowanie poszczególnych linii }
    for I := 0 to Pred(Memo.Lines.Count) do
    begin

      { po dojściu do końca strony zresetuj licznik linii }
      { i przejdź do nowej strony                         }

      Inc(LineCount);
      if LineCount = LinesPerPage then begin
        PrintFooter(R, LineHeight);
        LineCount := 4;
        Printer.NewPage;
      end;

      { pobierz kolejną linię Memo }
      S := Memo.Lines.Strings[I];
      Printer.Canvas.TextOut(0, LineCount * LineHeight, S);
    end;

    { zakończ drukowanie }
    PrintFooter(R, LineHeight);
    Printer.EndDoc;
  end;
end;


(comments are in Polish, don't care 'bout them)

PostPosted: June 17th, 2003, 3:37 pm
by richardchaven
Looking at the Preview.pas source code, I think if you do not use PrintPreview.Canvas, it will not show up.

Replace 'Printer.' with 'PrintPreview.' and 'Printer.BeginDoc' with 'PrintPreview.NewPage' and see what happens.

Cheers

PostPosted: June 17th, 2003, 4:01 pm
by Johnny_Bit
I did so, but page widith and height are incorrect. also DPI.

PostPosted: June 18th, 2003, 6:31 am
by richardchaven
PageHeight and PageWidth are in the .Units measure, not necessarily Pixels. You can use ConvertUnit or change the .Units property to mmPixels

Cheers

PostPosted: June 18th, 2003, 5:46 pm
by Johnny_Bit
Thanks, but I found solution just few minutes after disconect (by RichEdit way), but I've found bug in TPrintPreview: when I tried to change zoom to 100% then ecteption EOutOfResources raised, when I chenged Zoom to 50% it looked like zoom 500% or more! whats wrong 'bout it? [it hepend not only in my program, aslo in RichEdit print demo but it doesn't hapend in General demo.

And one more thing: why pages can't be scroled like in M$ word or Adobe Acrobat Reader(next page under previous)?

PostPosted: June 18th, 2003, 6:17 pm
by richardchaven
Look in their demo for paging: you have to set the CurrentPage property

PostPosted: June 19th, 2003, 9:33 am
by Johnny_Bit
OK, but what 'bout bug in zoom?

ps. CurrentPage sucks!

PostPosted: June 19th, 2003, 3:39 pm
by richardchaven
I don't know why you would get OutOfResources; I think you need to email the vendor so they take a look at it.

Why does .CurrentPage suck? If they have one canvas, how elese are they supposed to keep track?

PostPosted: June 19th, 2003, 6:46 pm
by Johnny_Bit
I don't know what you mean by sending mail to vendor (exacly this part. mail to vendor of what?), besides try out the RichText print demo and change zoom to 100%

It might be caused by MulDiv (in UpdateZoom procedure)...

It's strange but when i changed zoom to 8 it looks like 100% in Word or Acrobat. and i can bet that it's bug in Update zoom

PostPosted: June 21st, 2003, 2:16 pm
by Johnny_Bit
I found finally reason of bug! It was in CalculateViewSize function, in zsZoomOther section, whole function should be:
Code: Select all
function TPrintPreview.CalculateViewSize(const Space: TPoint): TPoint;
begin
  with FPaperView do
    case FZoomState of
      zsZoomOther:
      begin
        Result.X := ActualWidth(MulDiv(FPixels.X, FZoom*Screen.PixelsPerInch,GetDeviceCaps(Printer.Handle, LOGPIXELSX) * 100));{ActualWidth(MulDiv(FPixels.X, FZoom, 100));}
        Result.Y := ActualWidth(MulDiv(FPixels.Y, FZoom*Screen.PixelsPerInch,GetDeviceCaps(Printer.Handle, LOGPIXELSY) * 100));{ActualHeight(MulDiv(FPixels.Y, FZoom, 100));}
      end;
      zsZoomToWidth:
      begin
        Result.X := Space.X;
        Result.Y := ActualHeight(MulDiv(ActualWidth(Result.X), FPixels.Y, FPixels.X));
      end;
      zsZoomToHeight:
      begin
        Result.Y := Space.Y;
        Result.X := ActualWidth(MulDiv(ActualHeight(Result.Y), FPixels.X, FPixels.Y));
      end;
      zsZoomToFit:
      begin
        if (FPixels.Y / FPixels.X) < (Space.Y / Space.X) then
        begin
          Result.X := Space.X;
          Result.Y := ActualHeight(MulDiv(ActualWidth(Result.X), FPixels.Y, FPixels.X));
        end
        else
        begin
          Result.Y := Space.Y;
          Result.X := ActualWidth(MulDiv(ActualHeight(Result.Y), FPixels.X, FPixels.Y));
        end;
      end;
    end;
end;

PostPosted: June 24th, 2003, 5:59 pm
by richardchaven
Please summarize the changes you made.

PostPosted: June 24th, 2003, 7:02 pm
by Johnny_Bit
orginal code is in comment. changes ware maded only for
Code: Select all
Result.X := ActualWidth(MulDiv(FPixels.X, FZoom*Screen.PixelsPerInch,GetDeviceCaps(Printer.Handle, LOGPIXELSX) * 100));{ActualWidth(MulDiv(FPixels.X, FZoom, 100));<-orginal}
        Result.Y := ActualWidth(MulDiv(FPixels.Y, FZoom*Screen.PixelsPerInch,GetDeviceCaps(Printer.Handle, LOGPIXELSY) * 100));{ActualHeight(MulDiv(FPixels.Y, FZoom, 100));<-orginal}


it was in lines 1767 and 1768 of unit preview.pas in function CalculateViewSize (protected function of TPrintPreview). Is it enought?

PostPosted: June 25th, 2003, 12:15 am
by richardchaven
Thank you