Сохранение точных размеров при печати

Приведенный ниже модуль демонстрирует принцип использования GetDeviceCaps для получения исчерпывающей информации о вашем принтере, включая HORZRES и VERTRES (горизонтальное и вертикальное разрешение в пикселах) на дюйм бумаги. Используя значения LOGPIXELSX и LOGPIXELSY, вы можете откалибровать принтер для точного задания количества точек на дюйм в горизонтальном и вертикальном направлениях.

В дополнение к информации о принтере, приведенный модуль демонстрирует способ печати, при котором изображение выводится на принтер "естественного" размера; также показана возможность размещения изображения на бумаге в определенной позиции и определенного размера (т.е. с применением масштабирования). Я думаю это должно вам помочь в деле управления принтером.

Пример также демонстрирует вывод на печать синусной кривой в конкретной позиции печати с заданными в дюймах размерами. Я думаю вы без труда разберетесь как перейти на метрическую систему размеров.

 

    unit Tstpr2fm;

{Пример использования объекта Printer из модуля TPrinter.
Приведен избыточный стиль программирования для облегчения
восприятия материала.

Демонстрация величин, возвращаемых функцией Windows API GetDeviceCaps.

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Print: TButton;
Image1: TImage;
procedure PrintClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation
USES
Printers;

{Константы WINAPI GetDeviceCaps получены из C++ windows.h и wingdi.h}

{Отдельные константы здесь приведены только для информации о их наличии}
CONST
DRIVERVERSION   =   0;
TECHNOLOGY      =   2{Смотри windows.h для значения маски}
HORZSIZE        =   4;
VERTSIZE        =   6;
HORZRES         =   8;
VERTRES         =  10;
BITSPIXEL       =  12;
PLANES          =  14;
NUMBRUSHES      =  16;
NUMPENS         =  18;
NUMMARKERS      =  20;
NUMFONTS        =  22;
NUMCOLORS       =  24;
PDEVICESIZE     =  26;
CURVECAPS       =  28{Смотри windows.h для значения маски}
LINECAPS        =  30{Смотри windows.h для значения маски}
POLYGONALCAPS   =  32{Смотри windows.h для значения маски}
TEXTCAPS        =  34{Смотри windows.h для значения маски}
CLIPCAPS        =  36{Смотри windows.h для значения маски}
RASTERCAPS      =  38{Смотри windows.h для значения маски}
ASPECTX         =  40;
ASPECTY         =  42;
ASPECTXY        =  44;

LOGPIXELSX      =  88;
LOGPIXELSY      =  90;

SIZEPALETTE     = 104;
NUMRESERVED     = 106;
COLORRES        = 108;

PHYSICALWIDTH   = 110;   {Смотри определение в windows.h}
PHYSICALHEIGHT  = 111;   {Смотри определение в windows.h}
PHYSICALOFFSETX = 112;   {Смотри определение в windows.h}
PHYSICALOFFSETY = 113;   {Смотри определение в windows.h}
SCALINGFACTORX  = 114;   {Смотри определение в windows.h}
SCALINGFACTORY  = 115;   {Смотри определение в windows.h}

DeviceCapsString: ARRAY[1..34] OF STRING =
('DRIVERVERSION''TECHNOLOGY',     'HORZSIZE',
'VERTSIZE',       'HORZRES',        'VERTRES',
'BITSPIXEL',      'PLANES',         'NUMBRUSHES',
'NUMPENS',        'NUMMARKERS',     'NUMFONTS',
'NUMCOLORS',      'PDEVICESIZE',    'CURVECAPS',
'LINECAPS',       'POLYGONALCAPS''TEXTCAPS',
'CLIPCAPS',       'RASTERCAPS',     'ASPECTX',
'ASPECTY',        'ASPECTXY',       'LOGPIXELSX',
'LOGPIXELSY',     'SIZEPALETTE',    'NUMRESERVED',
'COLORRES',       'PHYSICALWIDTH''PHYSICALHEIGHT',
'PHYSICALOFFSETX','PHYSICALOFFSETY','SCALINGFACTORX',
'SCALINGFACTORY');

DeviceCapsIndex:  ARRAY[1..34] OF INTEGER =
0,   2,   4,   6,   8,  1012141618,
20222426283032343638,
4042448890, 104, 106, 108, 110, 111,
112, 113, 114, 115);

{$R *.DFM}

FUNCTION iPosition(const i:  INTEGER):  INTEGER;
BEGIN
RESULT := Integer(i * LongInt(Printer.PageWidth)  DIV 1000)
END {iPosition};


FUNCTION jPosition(const j:  INTEGER):  INTEGER;
BEGIN
RESULT := Integer(j * LongInt(Printer.PageHeight) DIV 1000)
END {jPosition};


procedure TForm1.PrintClick(Sender: TObject);
VAR
DestinationRectangle:  TRect;
GraphicAspectRatio  :  DOUBLE;
i                   :  INTEGER;
j                   :  INTEGER;
iBase               :  INTEGER;
iPixelsPerInch      :  WORD;
jBase               :  INTEGER;
jDelta              :  INTEGER;
jPixelsPerInch      :  WORD;
OffScreen           :  TBitMap;
PixelAspectRatio    :  DOUBLE;
SourceRectangle     :  TRect;
TargetRectangle     :  TRect;
value               :  INTEGER;
x                   :  DOUBLE;
y                   :  DOUBLE;
begin
Printer.Orientation := poLandscape;
Printer.BeginDoc;

{Делаем прямоугольник для показа полей}
Printer.Canvas.Rectangle(0,0, Printer.PageWidth, Printer.PageHeight);

{Свойства принтера и страницы}
Printer.Canvas.Font.Name := 'Times New Roman';
Printer.Canvas.Font.Size := 12;
Printer.Canvas.Font.Style := [fsBold];
Printer.Canvas.TextOut(iPosition(50), jPosition(40), 'Свойства принтера и страницы');

Printer.Canvas.Font.Style := [];
Printer.Canvas.Font.Size := 10;
iBase := iPosition(50);
jBase := 60;
jDelta := 18;
Printer.Canvas.TextOut(iPosition(50), jPosition(jBase),
Printer.Printers.Strings[Printer.PrinterIndex]);
INC (jBase, jDelta);

Printer.Canvas.TextOut(iBase, jPosition(jBase),
'Пикселей:  ' + IntToStr(Printer.PageWidth) + ' X ' +
IntToStr(Printer.PageHeight));
INC (jBase, jDelta);

Printer.Canvas.TextOut(iBase, jPosition(jBase),
'Дюймов:  ' + FormatFloat('0.000',
Printer.PageWidth / Printer.Canvas.Font.PixelsPerInch) + ' X ' +
FormatFloat('0.000',
Printer.PageHeight / Printer.Canvas.Font.PixelsPerInch));
INC (jBase, 2*jDelta);

Printer.Canvas.TextOut(iBase, jPosition(jBase),
'Шрифт:  ' + Printer.Canvas.Font.Name + '   Размер:  ' +
IntToStr(Printer.Canvas.Font.Size));
INC (jBase, jDelta);


Printer.Canvas.TextOut(iBase, jPosition(jBase),
'Пикселей в дюйме:  ' + IntToStr(Printer.Canvas.Font.PixelsPerInch));
INC (jBase, jDelta);

Printer.Canvas.TextOut(iBase, jPosition(jBase),
'''ТЕКСТ'':  ' + IntToStr(Printer.Canvas.TextWidth('ТЕКСТ')) + ' X ' +
IntToStr(Printer.Canvas.TextHeight('ТЕКСТ')) + '
пикселей');

{Значения GetDeviceCaps}
INC (jBase, 2*jDelta);
Printer.Canvas.Font.Size := 12;
Printer.Canvas.Font.Style := [fsBold];
Printer.Canvas.TextOut(iBase, jPosition(jBase), 'GetDeviceCaps');
INC (jBase, jDelta);

Printer.Canvas.Font.Size := 10;
Printer.Canvas.Font.Style := [];

FOR j := LOW(DeviceCapsIndex) TO HIGH(DeviceCapsIndex) DO
BEGIN
value := GetDeviceCaps(Printer.Handle, DeviceCapsIndex[j]);
Printer.Canvas.TextOut(iBase, jPosition(jBase), DeviceCapsString[j]);

IF   (DeviceCapsIndex[j] < 28) OR (DeviceCapsIndex[j] > 38)
THEN Printer.Canvas.TextOut(iPosition(250), jPosition(jBase), Format('%-8d',  [value]))
ELSE Printer.Canvas.TextOut(iPosition(250), jPosition(jBase), Format('%.4x', [value]));

INC (jBase, jDelta);

END;

{Помещаем изображение в левый нижний угол}
Printer.Canvas.Draw (iPosition(300), jPosition(100),
Form1.Image1.Picture.Graphic);

{Помещаем то же изображение, имеющее ширину 1" и пропорциональную
высоту в позиции 4"-правее и 1"-ниже верхнего левого угла}
GraphicAspectRatio := Form1.Image1.Picture.Height /
Form1.Image1.Picture.Width;

iPixelsPerInch := GetDeviceCaps(Printer.Handle, LOGPIXELSX);
jPixelsPerInch := GetDeviceCaps(Printer.Handle, LOGPIXELSY);
PixelAspectRatio := jPixelsPerInch / iPixelsPerInch;

TargetRectangle := Rect(4*iPixelsPerInch, {4"}
jPixelsPerInch,  {1"}
6*iPixelsPerInch,  {6" -- 2" ширина}
jPixelsPerInch +
TRUNC(2*iPixelsPerInch * GraphicAspectRatio *
PixelAspectRatio));

Printer.Canvas.TextOut(4*iPixelsPerInch, jPixelsPerInch -
Printer.Canvas.TextHeight('X'),
'2" ширина от (4", 1")');
Printer.Canvas.StretchDraw (TargetRectangle, Form1.Image1.Picture.Graphic);

{Создаем изображение в памяти и затем копируем его на холст принтера}
SourceRectangle := Rect (0,0, 3*iPixelsPerInch-12*jPixelsPerInch-1);

{Это не должно работать!  Rectangle = Left, Top, Right, Bottom
Top и Bottom считаются зарезервированными?}
DestinationRectangle := Rect(4*iPixelsPerInch,    6*jPixelsPerInch,
7*iPixelsPerInch-14*jPixelsPerinch-1);

Printer.Canvas.TextOut(4*iPixelsPerInch, 4*jPixelsPerInch -
Printer.Canvas.TextHeight('X'),
IntToStr(3*iPixelsPerInch) + ' пикселей на ' +
IntToStr(2*jPixelsPerInch) + ' пикселей -- ' +
'3"-на-2" в (4",4")');

OffScreen := TBitMap.Create;
TRY
OffScreen.Width  := SourceRectangle.Right  + 1;
OffScreen.Height := SourceRectangle.Bottom + 1;
WITH  OffScreen.Canvas DO
BEGIN
Pen.Color := clBlack;
Brush.Color := clWhite;
Rectangle(0,0, 3*iPixelsPerInch-1, 2*jPixelsPerInch-1);
Brush.Color := clRed;
MoveTo (0,0);
LineTo (3*iPixelsPerInch-1, 2*jPixelsPerInch-1);

Brush.Color := clBlue;
MoveTo (0,0);
FOR i := 0 TO 3*iPixelsPerInch - 1 DO
BEGIN
x := 12*PI*(i / (3*iPixelsPerInch - 1));
y := jPixelsPerInch + jPixelsPerInch*SIN(x);
LineTo (i, TRUNC(y));
END

END;

Printer.Canvas.CopyRect(DestinationRectangle, OffScreen.Canvas,
SourceRectangle);
FINALLY
OffScreen.Free
END;

{Список шрифтов для данного принтера}
iBase := iPosition(750);
Printer.Canvas.Font.Name := 'Times New Roman';
Printer.Canvas.Font.Size := 12;
Printer.Canvas.Font.Style := [fsBold];
Printer.Canvas.TextOut(iBase, jPosition(40), 'Шрифты');

Printer.Canvas.Font.Style := [];
Printer.Canvas.Font.Size := 10;
jDelta := 16;
FOR j := 0 TO Printer.Fonts.Count - 1 DO
BEGIN
Printer.Canvas.TextOut(iBase, jPosition(60 + jDelta*j), Printer.Fonts.Strings[j])
END;

Printer.EndDoc;

end;


end.
 
« Предыдущая статья   Следующая статья »