Printing 2 or more pages on 1

I would like to know how to print a content of Memo or RichEdit and how to set printer layout to print two or more pages on one page in A4 format. If you could recomend me some good components that do this or some example I would be very greateful.
vanja_ninkovicAsked:
Who is Participating?
 
mullet_attackConnect With a Mentor Commented:
Below is a unit that sub-classes TRichedit to print in two columns on A4
by overriding the Print method.

It is quick and dirty, tidy up by adding a NumColumns property for example

Small issue , the left column wraps, but the right hand doesn't. Shouldn't be too hard to fix.

unit RicheditCols;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, Richedit, printers;

type
  TRicheditCols = class(trichedit)
  private
    { Private declarations }
  protected
    { Protected declarations }
  public
    procedure Print(const Caption: string); override;
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TRicheditCols]);
end;


procedure TRicheditCols.Print(const Caption: string);
var
  Range: TFormatRange;
  LastChar, MaxLen, LogX, LogY, OldMap: Integer;
  SaveRect: TRect;
  LeftHalf : boolean;
  L, M, R : integer; // left , middle and right edges
begin
  FillChar(Range, SizeOf(TFormatRange), 0);
  with Printer, Range do
  begin
    Title := Caption;
    BeginDoc;
    hdc := Handle;
    hdcTarget := hdc;
    LogX := GetDeviceCaps(Handle, LOGPIXELSX);
    LogY := GetDeviceCaps(Handle, LOGPIXELSY);
    if IsRectEmpty(PageRect) then
    begin
      rc.right := PageWidth * 1440 div LogX;
      rc.bottom := PageHeight * 1440 div LogY;
      l := rc.left;
      m := rc.right div 2;
      r := rc.right;
    end
    else begin
      rc.left := PageRect.Left * 1440 div LogX;
      rc.top := PageRect.Top * 1440 div LogY;
      rc.right := (PageRect.Right * 1440 div LogX);
      rc.bottom := PageRect.Bottom * 1440 div LogY;
      l := rc.left;
      m := rc.right div 2;
      r := rc.right;
    end;
    LeftHalf := true;
    rc.left := l;
    rc.right := m;

    rcPage := rc;
    SaveRect := rc;
    LastChar := 0;
    MaxLen := GetTextLen;
    chrg.cpMax := -1;

    // ensure printer DC is in text map mode
    OldMap := SetMapMode(hdc, MM_TEXT);
    SendMessage(Self.Handle, EM_FORMATRANGE, 0, 0);    // flush buffer
    try
      repeat
        rc := SaveRect;
        chrg.cpMin := LastChar;
        LastChar := SendMessage(Self.Handle, EM_FORMATRANGE, 1, Longint(@Range));
        if (LastChar < MaxLen) and (LastChar <> -1) then
          if Lefthalf then
            begin
              rc.left := m;
              rc.right := r * 2;
              lefthalf := false;
              SaveRect := rc;
            end
          else
            begin
              rc.left := l;
              rc.right := m;
              lefthalf := true;
              SaveRect := rc;
              NewPage; //only if we just printed the right-hand half
            end;

      until (LastChar >= MaxLen) or (LastChar = -1);
      EndDoc;
    finally
      SendMessage(Self.Handle, EM_FORMATRANGE, 0, 0);  // flush buffer
      SetMapMode(hdc, OldMap);       // restore previous map mode
    end;
  end;
end;

end.
0
 
NetoManCommented:
The easiest way for me is put this field in a Qreport form. From there you can set any page format you want.

0
 
RadlerCommented:
A little sample:
procedure TForm1.Button1Click(Sender:TObject);

var
  I, Start, Stop: Integer;
begin
PrintDialog1.Options := [poPageNums, poSelection];
PrintDialog1.FromPage := 1;
PrintDialog1.MinPage := 1;
PrintDialog1.ToPage := PageControl1.PageCount;
PrintDialog1.MaxPage := PageControl1.PageCount;
if PrintDialog1.Execute then
  begin
  { determine the range the user wants to print }
  with PrintDialog1 do
  begin
    if PrintRange = prAllPages then

      begin
      Start := MinPage - 1;
      Stop := MaxPage - 1;
      end
    else if PrintRange = prSelection then
      begin
      Start := PageControl1.ActivePage.PageIndex;
      Stop := Start;
      end
    else  { PrintRange = prPageNums }
      begin
      Start := FromPage - 1;
      Stop := ToPage - 1;
      end;
  end;
  { now, print the pages }
  with Printer do

    begin
    BeginDoc;
    for I := Start to Stop do
      begin
      PageControl1.Pages[I].PaintTo(Handle, 10, 10);
      if I <> Stop then
        NewPage;
      end;
    EndDoc;
    end;
  end;
end;

Notes : Adds Printers at Uses clause and put a PrintDialog component too

I avoid use Quickreport, because the function
ProgWorks( Codex, Delphi(x), QR(x))=True
ProgWorks( Codex, Delphi(x+1), QR(x+1))=BrainStorm;

T++, Radler.
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
vanja_ninkovicAuthor Commented:
Adjusted points from 100 to 150
0
 
vanja_ninkovicAuthor Commented:
I dont need printing of PageControl.pages. What I was refering to is that I have one TRichEdit on a form that has a lot of text in it, when I execute RichEdit.print it prints its content on 10 A4 papers, but most of the text is on right side of A4 papers and more then half of paper is blank.My question is how to put content of 2 or more A4 papers on one A4 paper, in that way user is using all available paper space and saves the paper.It is very important that the text in RichEdit is not changed, so if you have any solution please answer.I tried QMemo component of CBSuite collection and it choice of pagelayout was great but it is ShareWare and expencive for my budget.  
and yes I would really like to avoid using QReport.
0
 
RadlerCommented:
--------------------------
|             |              |
|   ____   |      ___   |
|   | 1 |    |     | 2 |   |
|   |---|    |     |---|   |
|             |              |
-------------------------
|             |              |
|   ____   |     ____  |
|   | 3 |    |     | 4 |   |
|   |---|    |     |---|   |
|             |               |
--------------------------

Suppossing like this, We'll have some invitables troubles, but if is your desire, Correct ?

0
 
vanja_ninkovicAuthor Commented:
Adjusted points from 150 to 250
0
 
vanja_ninkovicAuthor Commented:
Yes, that is exactly what I need. If you could help me with some example code that does that I would be very,very greateful. Also I will increase points for this question. Thanks once more for your efort.
0
 
RadlerCommented:
I'll try, wait for news tomorrow.
T++, Radler.
0
 
vanja_ninkovicAuthor Commented:
This is the basic that I need. With a little coding and a little repairs I think this will do the trick. I will accept this answer. Thank you for this good peace of code, and also I want to thank you for your time and efort.
0
All Courses

From novice to tech pro — start learning today.