Quote
In article <3b8f8c20$1_1@dnews>, Dmitri Papichev wrote:
> That is definitely the fact that my printer receives and prints pages as
> soon as NewPage is performed.
> Peter, could you please elaborate how to make it without BeginDoc? I tried,
> but just to end up with "Printer is not currently printing" error.
To count pages you do not actually perform any output on the printer canvas,
you simply calculate the positions of the output. The main problem here is
that you need a canvas for measuring text and this canvas needs to have the
same logical resolution than the printer canvas has. I never needed to do
this, so the following is just an idea: create a metafile and use its canvas:
procedure TForm1.Button1Click(Sender: TObject);
var
mf: TMetafile;
mfc: TMetafileCanvas;
begin
mf:= TMetafile.Create;
try
mfc:= TMetafilecanvas.create( mf, printer.handle );
try
mf.width := printer.pagewidth;
mf.height := printer.pageheight;
mfc.font.pixelsperinch := GetDeviceCaps( printer.handle, LOGPIXELSY );
...measure using mfc
finally
mfc.free
end;
finally
mf.Free;
end;
end;
The docs are not implicit here but you can use an information context handle
as a reference "DC" for TMetafilecanvas.Create. The result after the code
above is a metafile with the same size as a printed page and the same logical
resolution. It has MM_TEXT mapping mode, the same the printer canvas uses as
default.
OK, how to integrate this with the printing code you already have? Of course
you do not want to write two different versions of the same code. So lets
apply the proxy pattern: instead of directly working with the printer object
your printing routine is handed a class that offers the same methods (and a
canvas) than the printer object. For the actual printing this object will pass
on the requests to the Printer object, for the page counting another object is
used that provides the metafile canvas, has empty BeginDoc, EndDoc and Abort
methods and a NewPage method that counts pages instead of ejecting them.
The following is a sketch on how such objects may look like. I leave the
testing to you <g>.
unit PrinterProxies;
interface
Uses Windows, Classes, graphics;
Type
TBasePrinterProxy = class
private
FhIC: THandle;
function GetCanvas: Tcanvas; virtual; abstract;
function Getpageheight: Integer;
function GetPagenumber: Integer; virtual; abstract;
function Getpagewidth: Integer;
protected
property hIC: THandle read FhIC;
public
Constructor Create; virtual;
Function DeviceCaps( index: Integer ): Integer;
Procedure BeginDoc; virtual;
Procedure EndDoc; virtual;
Procedure NewPage; virtual;
Procedure Abort; virtual;
property Canvas: Tcanvas read GetCanvas;
property Pagewidth: Integer read Getpagewidth;
property Pageheight: Integer read Getpageheight;
property Pagenumber: Integer read GetPagenumber;
end;
TPagecounter = class( TBasePrinterProxy )
private
FPagecount: Integer;
FMetafile: TMetafile;
FMetafilecanvas: TMetafilecanvas;
function GetCanvas: Tcanvas; override;
function GetPagenumber: Integer; override;
procedure initCanvas;
public
Constructor Create; override;
Destructor Destroy; override;
Procedure BeginDoc; override;
Procedure NewPage; override;
end;
TPrinterProxy = class( TBasePrinterProxy )
private
function GetCanvas: Tcanvas; override;
function GetPagenumber: Integer; override;
public
Procedure BeginDoc; override;
Procedure NewPage; override;
Procedure EndDoc; override;
Procedure Abort; override;
end;
implementation
uses sysutils, printers;
{ TBasePrinterProxy }
procedure TBasePrinterProxy.Abort;
begin { does nothing } end;
procedure TBasePrinterProxy.BeginDoc;
begin { does nothing } end;
constructor TBasePrinterProxy.Create;
begin
inherited;
Assert( not printer.printing );
FhIC := Printer.Handle;
end;
function TBasePrinterProxy.DeviceCaps(index: Integer): Integer;
begin
result := GetDeviceCaps( FhIC, index );
end;
procedure TBasePrinterProxy.EndDoc;
begin { does nothing } end;
function TBasePrinterProxy.Getpageheight: Integer;
begin
Result := printer.PageHeight;
end;
function TBasePrinterProxy.Getpagewidth: Integer;
begin
Result := printer.PageWidth;
end;
procedure TBasePrinterProxy.NewPage;
begin { does nothing } end;
{ TPagecounter }
procedure TPagecounter.BeginDoc;
begin
FPagecount := 1;
end;
constructor TPagecounter.Create;
begin
inherited;
FMetafile := TMetafile.Create;
InitCanvas;
end;
destructor TPagecounter.Destroy;
begin
FMetafilecanvas.Free;
FMetafile.Free;
inherited;
end;
function TPagecounter.GetCanvas: Tcanvas;
begin
Result := FMetafilecanvas;
end;
function TPagecounter.GetPagenumber: Integer;
begin
Result := FPagecount;
end;
procedure TPagecounter.initCanvas;
begin
FMetafilecanvas := TMetafilecanvas.Create( FMetafile, hIC );
FMetafile.Width := Pagewidth;
FMetafile.Height := Pageheight;
FMetafileCanvas.Font.PixelsPerInch := DeviceCaps( LOGPIXELSY );
end;
procedure TPagecounter.NewPage;
begin
Inc( FPageCount );
FreeAndNil( FMetafilecanvas );
FMetafile.Clear;
initCanvas;
end;
{ TPrinterProxy }
procedure TPrinterProxy.Abort;
begin
Printer.Abort;
end;
procedure TPrinterProxy.BeginDoc;
begin
Printer.BeginDoc;
end;
procedure TPrinterProxy.EndDoc;
begin
Printer.EndDoc;
end;
function TPrinterProxy.GetCanvas: Tcanvas;
begin
Result := Printer.Canvas;
end;
function TPrinterProxy.GetPagenumber: Integer;
begin
Result := Printer.PageNumber;
end;
procedure TPrinterProxy.NewPage;
begin
Printer.NewPage;
end;
end.
Peter Below (TeamB) 100113.1...@compuserve.com)
No e-mail responses, please, unless explicitly requested!
Note: I'm unable to visit the newsgroups every day at the moment,
so be patient if you don't get a reply immediately.