procedure Thtml.Print(FromPage, ToPage: integer);
var
ARect: TRect;
PrintList: TSectionList;
P1, P2, P3, W, H, Index, Dummy: integer;
HTop, HBot: LongInt;
LineTop, Curs: LongInt;
do
ne: boolean;
DC : HDC;
SaveFont: TFont;
SaveSize: integer;
{ added to query the printer for printable area }
QEsc: integer;
UpperLeftPagePoint, { these will contain Top/Left and Bottom/Right
unprintable area}
LowerRightPagePoint: TPoint;
{ added for "local" coordinate system }
MLeft: integer;
MLeftPrn: integer;
MRightPrn: integer;
MTopPrn: integer;
MBottomPrn: integer;
TopPixels, TopPixelsPrn, HPrn, WPrn: integer;
hrgnClip: THandle;
savedFont : TFont ;
savedPen : TPen ;
savedBrush : TBrush ;
Align, ScaledPgHt, ScaledPgWid: integer;
begin
FPage := 0;
if FProcessing or (SectionList.Count = 0) then
Exit;
PrintList := TSectionList.CreateCopy(SectionList);
PrintList.SetYOffset(0);
try
savedFont := TFont.Create ;
savedPen := TPen.Create ;
savedBrush := TBrush.Create ;
try
PrintList.Printing := True;
PrintList.SetBackground(clWhite);
FPage := 1;
try
with Printer, Canvasdo
begin
hRgnClip := 0;
if (Printer.Title = '') and (DocumentTitle <> '') then
Printer.Title :=do
cumentTitle ;
begin
Doc;
DC := Canvas.Handle;
SaveFont := TFont.Create;
SaveFont.Assign(Canvas.Font);
P3 := GetDeviceCaps(DC, LOGPIXELSY);
P2 := Screen.PixelsPerInch;
Canvas.Font.PixelsPerInch := P2;
{use screen pixels for ThtmlViewer}
SetMapMode(DC, mm_AnIsotropic);
P1 := GetDeviceCaps(DC, LOGPIXELSX);
SetWindowExtEx(DC, P2, P2, Nil);
SetViewPortExtEx(DC, P1,P3, Nil);
{ calculate the amount of space that is non-printable }
{ get PHYSICAL page width }
QEsc := GetPhysPageSize;
if Escape(Printer.Handle, QueryEscSupport, sizeof(Integer),
@QEsc, NIL)>0 then
Escape(Printer.Handle, GetPhysPageSize, 0, NIL, @LowerRightPagePoint)
else
{ command NOT supported !}
with LowerRightPagePointdo
begin
x := -1;
y := -1;
{ signal that these values are not good at all...}
end;
{ now compute a complete unprintable area rectangle (composed of 2*width,
2*height) in pixels...}
with LowerRightPagePointdo
begin
y := y - GetDeviceCaps(DC, VertRes);
x := x - GetDeviceCaps(DC, HorzRes);
end;
{ get upper left physical offset for the printer... ->
printable area <> paper size }
QEsc := GetPrintingOffset;
if Escape(Printer.Handle, QueryEscSupport, sizeof(Integer),
@QEsc, NIL)>0 then
Escape(Printer.Handle, GetPrintingOffset, 0, NIL, @UpperLeftPagePoint)
else
with UpperLeftPagePointdo
begin
x := 0;
y := 0;
{ assume there is no physical offset ?! }
end;
{ now that we know the TOP and LEFT offset we finally can
compute the BOTTOM and RIGHT offset: }
with LowerRightPagePointdo
begin
x := x - UpperLeftPagePoint.x;
{ wedo
n't want to have negative values}
if x < 0 then
x := 0;
{ assume no right printing offset }
y := y - UpperLeftPagePoint.x;
{ wedo
n't want to have negative values}
if y < 0 then
y := 0;
{ assume no bottom printing offset }
end;
{ which results in LowerRightPoint containing the BOTTOM
and RIGHT unprintable
area offset;
using these we modify the (logical, true)
borders...}
MLeftPrn := trunc(FPrintMarginLeft/2.54 * P1);
MLeftPrn := MLeftPrn - UpperLeftPagePoint.x;
{ subtract physical offset }
MLeft := MulDiv(MLeftPrn, P2, P1);
MRightPrn := trunc(FPrintMarginRight/2.54 * P1);
MRightPrn := MRightPrn - LowerRightPagePoint.x;
{ subtract physical offset }
WPrn := PageWidth - (MLeftPrn + MRightPrn);
W := MulDiv(WPrn, P2, P1);
Curs := 0;
PrintList.DoLogic(Canvas, 0, W, Dummy, Curs);
MTopPrn := trunc(FPrintMarginTop/2.54 * P3);
MTopPrn := MTopPrn - UpperLeftPagePoint.y;
{ subtract physical offset }
MBottomPrn := trunc(FPrintMarginBottom/2.54 * P3);
MBottomPrn := MBottomPrn - LowerRightPagePoint.y;
{ subtract physical offset }
TopPixelsPrn := MTopPrn - UpperLeftPagePoint.y;
{ subtract physical offset }
TopPixels := MulDiv(TopPixelsPrn, P2, P3);
HPrn := PageHeight-(MTopPrn+MBottomPrn);
H := MulDiv(HPrn, P2, P3);
{scaled pageHeight}
do
ne := False;
HTop := 0;
ScaledPgHt := MulDiv(PageHeight, P2, P3);
ScaledPgWid := MulDiv(PageWidth, P2, P3);
hrgnClip := CreateRectRgn(0, TopPixelsPrn-1, WPrn + MLeftPrn+2,
TopPixelsPrn + HPrn + 2);
ARect := Rect(MLeft, TopPixels, W + MLeft, TopPixels + H);
while (FPage <= ToPage) and notdo
nedo
begin
PrintList.SetYOffset(HTop-TopPixels);
HBot := HTop + H;
SetMapMode(DC, mm_AnIsotropic);
SetWindowExtEx(DC, P2, P2, Nil);
SetViewPortExtEx(DC, P1,P3, Nil);
SetWindowOrgEx(DC, 0, 0, Nil);
SelectClipRgn(DC, hrgnClip);
if FPage >= FromPage then
begin
PrintList.Draw(Canvas, ARect, W, MLeft, 0);
if Assigned(FOnPrintHeader) or Assigned(FOnPrintFooter) then
begin
{ preserve current settings of the Canvas, in case user
would make changes and not restore them back }
savedFont.Assign (Canvas.Font);
savedPen.Assign (Canvas.Pen);
savedBrush.Assign (Canvas.Brush);
SelectClipRgn(DC, 0);
{White out excess printing}
Canvas.Brush.Color := clWhite;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := clWhite;
Canvas.Rectangle(MLeft, 0, W + MLeft, TopPixels-1);
Canvas.Rectangle(MLeft, PrintList.PageBottom-HTop+TopPixels,
W + MLeft, TopPixels+H);
Align := SetTextAlign(DC, TA_Top or TA_Left or TA_NOUPDATECP);
if Assigned(FOnPrintHeader) then
begin
SetWindowOrgEx(DC, 0, 0, Nil);
FOnPrintHeader(Self, Canvas, FPage, ScaledPgWid, TopPixels,do
ne);
end;
if Assigned(FOnPrintFooter) then
begin
SetWindowOrgEx(DC, 0, -(TopPixels+H), Nil);
FOnPrintFooter(Self, Canvas, FPage, ScaledPgWid,
ScaledPgHt-(TopPixels+H),do
ne);
end;
{ restore initial Canvas settings }
Canvas.Font.Assign(savedFont);
Canvas.Pen.Assign(savedPen);
Canvas.Brush.Assign(savedBrush);
SetTextAlign(DC, Align);
end;
end
else
PrintList.Draw(Canvas, ARect, W, MLeft+3*W, 0);
{off page}
HTop := PrintList.PageBottom;
if PrintList.FindLineAtPosition(HTop, LineTop, Index) = Nil then
do
ne := True;
if notdo
ne and (FPage >= FromPage) and (FPage < ToPage) then
NewPage;
Inc(FPage);
end;
end;
finally
if (FromPage > FPage) then
Printer.Abort;
Printer.EndDoc;
Dec(FPage);
if hRgnClip <> 0 then
DeleteObject(hrgnClip);
Printer.Canvas.Font.Assign(SaveFont);
{restore font for others}
SaveSize := Printer.Canvas.Font.Size;
Printer.Canvas.Font.PixelsPerInch := P3;
Printer.Canvas.Font.Size := SaveSize;
SaveFont.Free;
Printer.Title := '';
end;
finally
savedFont.Free;
savedPen.Free;
savedBrush.Free;
end;
finally
PrintList.Free;
end;
end;