diff --git a/components/printers/readme.txt b/components/printers/readme.txt
index b194c69266..0334fa1021 100644
--- a/components/printers/readme.txt
+++ b/components/printers/readme.txt
@@ -4,18 +4,23 @@ Printer4Lazarus package
This package add some components.
TPrinterSetupDialog : for update properties of selected printer
TPrintDialog : for select and/or update an printer before printing
- TPageSetupDialog : to select margins (currently only under Windows)
+ TPageSetupDialog : to select margins (currently only under Windows)
Win32 :
Native implementation
+
Notes:
- 1. TPrinter.CanRenderCopies return information if printer driver is able to print more then one copy at once.
- Not all printers drivers support that feature (n that case programmer should print document requested times)
+ 1. TPrinter.CanRenderCopies return information if printer driver is able to print more then one copy at once.
+ Not all printers drivers support that feature (n that case programmer should print document requested times)
- 2.TPrintDialog.Options indicate which controls should be visible in dialog.
- TPrintDialog.PrintToFile indicate that output will be redirected to file.
+ 2. TPrintDialog.Options indicate which controls should be visible in dialog.
+ TPrintDialog.PrintToFile indicate that output will be redirected to file.
+
+ 3. Known Issue: After adjusting resolution using Printer.AdvancedProperties. The DevMode structure
+ shows the change correcly, but getting the value through Printer.XDPI the value is the old one.
+ However after using the PrintSetup dialog, it returns the correct value. Other changes like
+ the selected paper are correctly modified after AdvancedProperties, ... (?).
- 3.Some (mostly advanced) settings of printer driver are not preserved between two calls to TPrintDialog.Execute function.
Linux :
diff --git a/components/printers/sample/frmselprinter.lfm b/components/printers/sample/frmselprinter.lfm
index 29ca87fe25..397a0763a4 100644
--- a/components/printers/sample/frmselprinter.lfm
+++ b/components/printers/sample/frmselprinter.lfm
@@ -1,16 +1,16 @@
object Form1: TForm1
ActiveControl = Button2
Caption = 'Form1'
- ClientHeight = 487
+ ClientHeight = 507
ClientWidth = 339
OnCreate = FormCreate
PixelsPerInch = 96
Position = poDesktopCenter
HorzScrollBar.Page = 338
- VertScrollBar.Page = 486
- Left = 230
- Height = 487
- Top = 36
+ VertScrollBar.Page = 506
+ Left = 190
+ Height = 507
+ Top = 45
Width = 339
object Label1: TLabel
Caption = 'This sample show how to use the printer dialogs'
@@ -19,10 +19,10 @@ object Form1: TForm1
Left = 16
Height = 14
Top = 8
- Width = 226
+ Width = 230
end
object Button2: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Execute TPrinterSetupDialog'
OnClick = Button2Click
TabOrder = 0
@@ -32,7 +32,7 @@ object Form1: TForm1
Width = 320
end
object Button1: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Execute TPrintDialog'
OnClick = Button1Click
TabOrder = 1
@@ -60,15 +60,17 @@ object Form1: TForm1
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goSmoothScroll]
RowCount = 15
ScrollBars = ssAutoBoth
+ TabOrder = 7
+ TabStop = True
VisibleColCount = 1
VisibleRowCount = 14
Left = 8
- Height = 288
+ Height = 304
Top = 192
Width = 320
end
object Button3: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Get default printer info'
OnClick = Button3Click
TabOrder = 2
@@ -78,7 +80,7 @@ object Form1: TForm1
Width = 320
end
object Button4: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Print test'
OnClick = Button4Click
TabOrder = 3
@@ -88,7 +90,7 @@ object Form1: TForm1
Width = 69
end
object Button5: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Update printer state info'
OnClick = Button5Click
TabOrder = 4
@@ -98,7 +100,7 @@ object Form1: TForm1
Width = 224
end
object Button6: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Show printer properties'
OnClick = Button6Click
TabOrder = 5
@@ -108,7 +110,7 @@ object Form1: TForm1
Width = 224
end
object Button7: TButton
-
+ BorderSpacing.InnerBorder = 4
Caption = 'Execute TPageSetupDialog'
OnClick = Button7Click
TabOrder = 6
diff --git a/components/printers/sample/frmselprinter.lrs b/components/printers/sample/frmselprinter.lrs
index 558d425e91..31603d9a02 100644
--- a/components/printers/sample/frmselprinter.lrs
+++ b/components/printers/sample/frmselprinter.lrs
@@ -1,40 +1,45 @@
+{ This is an automatically generated lazarus resource file }
+
LazarusResources.Add('TForm1','FORMDATA',[
'TPF0'#6'TForm1'#5'Form1'#13'ActiveControl'#7#7'Button2'#7'Caption'#6#5'Form1'
- +#12'ClientHeight'#3#231#1#11'ClientWidth'#3'S'#1#8'OnCreate'#7#10'FormCreate'
+ +#12'ClientHeight'#3#251#1#11'ClientWidth'#3'S'#1#8'OnCreate'#7#10'FormCreate'
+#13'PixelsPerInch'#2'`'#8'Position'#7#15'poDesktopCenter'#18'HorzScrollBar.P'
- +'age'#3'R'#1#18'VertScrollBar.Page'#3#230#1#4'Left'#3#230#0#6'Height'#3#231#1
- +#3'Top'#2'$'#5'Width'#3'S'#1#0#6'TLabel'#6'Label1'#7'Caption'#6'/This sample'
+ +'age'#3'R'#1#18'VertScrollBar.Page'#3#250#1#4'Left'#3#190#0#6'Height'#3#251#1
+ +#3'Top'#2'-'#5'Width'#3'S'#1#0#6'TLabel'#6'Label1'#7'Caption'#6'/This sample'
+' show how to use the printer dialogs'#5'Color'#7#6'clNone'#11'ParentColor'#8
- +#4'Left'#2#16#6'Height'#2#14#3'Top'#2#8#5'Width'#3#226#0#0#0#7'TButton'#7'Bu'
- +'tton2'#7'Caption'#6#27'Execute TPrinterSetupDialog'#7'OnClick'#7#12'Button2'
- +'Click'#8'TabOrder'#2#0#4'Left'#2#8#6'Height'#2#27#3'Top'#2'3'#5'Width'#3'@'
- +#1#0#0#7'TButton'#7'Button1'#7'Caption'#6#20'Execute TPrintDialog'#7'OnClick'
- +#7#12'Button1Click'#8'TabOrder'#2#1#4'Left'#2#8#6'Height'#2#27#3'Top'#2'N'#5
- +'Width'#3'@'#1#0#0#11'TStringGrid'#5'SGrid'#15'AutoFillColumns'#9#11'BorderS'
- +'tyle'#7#6'bsNone'#8'ColCount'#2#2#7'Columns'#14#1#7'MinSize'#2'<'#7'MaxSize'
- +#3'^'#1#8'ReadOnly'#9#13'Title.Caption'#6#11'Information'#5'Width'#3#230#0#0
- +#0#15'DefaultColWidth'#2'Z'#10'FixedColor'#7#9'clBtnFace'#4'Flat'#9#13'GridL'
- +'ineWidth'#2#0#7'Options'#11#15'goFixedVertLine'#15'goFixedHorzLine'#10'goVe'
- +'rtLine'#10'goHorzLine'#13'goRangeSelect'#14'goSmoothScroll'#0#8'RowCount'#2
- +#15#10'ScrollBars'#7#10'ssAutoBoth'#15'VisibleColCount'#2#1#15'VisibleRowCou'
- +'nt'#2#14#4'Left'#2#8#6'Height'#3' '#1#3'Top'#3#192#0#5'Width'#3'@'#1#0#0#7
- +'TButton'#7'Button3'#7'Caption'#6#24'Get default printer info'#7'OnClick'#7
- +#12'Button3Click'#8'TabOrder'#2#2#4'Left'#2#8#6'Height'#2#27#3'Top'#2'i'#5'W'
- +'idth'#3'@'#1#0#0#7'TButton'#7'Button4'#7'Caption'#6#10'Print test'#7'OnClic'
- +'k'#7#12'Button4Click'#8'TabOrder'#2#3#4'Left'#3#0#1#6'Height'#2#27#3'Top'#3
- +#155#0#5'Width'#2'E'#0#0#7'TButton'#7'Button5'#7'Caption'#6#25'Update printe'
- +'r state info'#7'OnClick'#7#12'Button5Click'#8'TabOrder'#2#4#4'Left'#2#8#6'H'
- +'eight'#2#25#3'Top'#3#132#0#5'Width'#3#224#0#0#0#7'TButton'#7'Button6'#7'Cap'
- +'tion'#6#23'Show printer properties'#7'OnClick'#7#12'Button6Click'#8'TabOrde'
- +'r'#2#5#4'Left'#2#8#6'Height'#2#25#3'Top'#3#157#0#5'Width'#3#224#0#0#0#7'TBu'
- +'tton'#7'Button7'#7'Caption'#6#24'Execute TPageSetupDialog'#7'OnClick'#7#12
- +'Button7Click'#8'TabOrder'#2#6#4'Left'#2#8#6'Height'#2#27#3'Top'#2#24#5'Widt'
- +'h'#3'@'#1#0#0#19'TPrinterSetupDialog'#3'PSD'#5'Title'#6#20'Testing dialog t'
- +'itle'#4'left'#3#176#0#3'top'#3#240#0#0#0#12'TPrintDialog'#2'PD'#7'Collate'#9
- +#6'Copies'#2#1#8'FromPage'#2#2#7'MinPage'#2#2#7'MaxPage'#2#5#7'Options'#11#13
- +'poPrintToFile'#10'poPageNums'#11'poSelection'#9'poWarning'#6'poHelp'#0#11'P'
- +'rintToFile'#9#6'ToPage'#2#3#5'Title'#6#13'Testing title'#4'left'#3#176#0#3
- +'top'#3#16#1#0#0#10'TPopupMenu'#10'PopupMenu1'#4'left'#3#216#0#3'top'#3#240#0
- +#0#0#16'TPageSetupDialog'#5'PAGED'#5'Title'#6#25'Ustawienie strony raportu'#4
- +'left'#3#176#0#3'top'#3'0'#1#0#0#0
+ +#4'Left'#2#16#6'Height'#2#14#3'Top'#2#8#5'Width'#3#230#0#0#0#7'TButton'#7'Bu'
+ +'tton2'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#27'Execute TPrinterSe'
+ +'tupDialog'#7'OnClick'#7#12'Button2Click'#8'TabOrder'#2#0#4'Left'#2#8#6'Heig'
+ +'ht'#2#27#3'Top'#2'3'#5'Width'#3'@'#1#0#0#7'TButton'#7'Button1'#25'BorderSpa'
+ +'cing.InnerBorder'#2#4#7'Caption'#6#20'Execute TPrintDialog'#7'OnClick'#7#12
+ +'Button1Click'#8'TabOrder'#2#1#4'Left'#2#8#6'Height'#2#27#3'Top'#2'N'#5'Widt'
+ +'h'#3'@'#1#0#0#11'TStringGrid'#5'SGrid'#15'AutoFillColumns'#9#11'BorderStyle'
+ +#7#6'bsNone'#8'ColCount'#2#2#7'Columns'#14#1#7'MinSize'#2'<'#7'MaxSize'#3'^'
+ +#1#8'ReadOnly'#9#13'Title.Caption'#6#11'Information'#5'Width'#3#230#0#0#0#15
+ +'DefaultColWidth'#2'Z'#10'FixedColor'#7#9'clBtnFace'#4'Flat'#9#13'GridLineWi'
+ +'dth'#2#0#7'Options'#11#15'goFixedVertLine'#15'goFixedHorzLine'#10'goVertLin'
+ +'e'#10'goHorzLine'#13'goRangeSelect'#14'goSmoothScroll'#0#8'RowCount'#2#15#10
+ +'ScrollBars'#7#10'ssAutoBoth'#8'TabOrder'#2#7#7'TabStop'#9#15'VisibleColCoun'
+ +'t'#2#1#15'VisibleRowCount'#2#14#4'Left'#2#8#6'Height'#3'0'#1#3'Top'#3#192#0
+ +#5'Width'#3'@'#1#0#0#7'TButton'#7'Button3'#25'BorderSpacing.InnerBorder'#2#4
+ +#7'Caption'#6#24'Get default printer info'#7'OnClick'#7#12'Button3Click'#8'T'
+ +'abOrder'#2#2#4'Left'#2#8#6'Height'#2#27#3'Top'#2'i'#5'Width'#3'@'#1#0#0#7'T'
+ +'Button'#7'Button4'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#10'Print '
+ +'test'#7'OnClick'#7#12'Button4Click'#8'TabOrder'#2#3#4'Left'#3#0#1#6'Height'
+ +#2#27#3'Top'#3#155#0#5'Width'#2'E'#0#0#7'TButton'#7'Button5'#25'BorderSpacin'
+ +'g.InnerBorder'#2#4#7'Caption'#6#25'Update printer state info'#7'OnClick'#7
+ +#12'Button5Click'#8'TabOrder'#2#4#4'Left'#2#8#6'Height'#2#25#3'Top'#3#132#0#5
+ +'Width'#3#224#0#0#0#7'TButton'#7'Button6'#25'BorderSpacing.InnerBorder'#2#4#7
+ +'Caption'#6#23'Show printer properties'#7'OnClick'#7#12'Button6Click'#8'TabO'
+ +'rder'#2#5#4'Left'#2#8#6'Height'#2#25#3'Top'#3#157#0#5'Width'#3#224#0#0#0#7
+ +'TButton'#7'Button7'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#24'Execu'
+ +'te TPageSetupDialog'#7'OnClick'#7#12'Button7Click'#8'TabOrder'#2#6#4'Left'#2
+ +#8#6'Height'#2#27#3'Top'#2#24#5'Width'#3'@'#1#0#0#19'TPrinterSetupDialog'#3
+ +'PSD'#5'Title'#6#20'Testing dialog title'#4'left'#3#176#0#3'top'#3#240#0#0#0
+ +#12'TPrintDialog'#2'PD'#7'Collate'#9#6'Copies'#2#1#8'FromPage'#2#2#7'MinPage'
+ +#2#2#7'MaxPage'#2#5#7'Options'#11#13'poPrintToFile'#10'poPageNums'#11'poSele'
+ +'ction'#9'poWarning'#6'poHelp'#0#11'PrintToFile'#9#6'ToPage'#2#3#5'Title'#6
+ +#13'Testing title'#4'left'#3#176#0#3'top'#3#16#1#0#0#10'TPopupMenu'#10'Popup'
+ +'Menu1'#4'left'#3#216#0#3'top'#3#240#0#0#0#16'TPageSetupDialog'#5'PAGED'#5'T'
+ +'itle'#6#25'Ustawienie strony raportu'#4'left'#3#176#0#3'top'#3'0'#1#0#0#0
]);
diff --git a/components/printers/sample/frmselprinter.pas b/components/printers/sample/frmselprinter.pas
index 0f710d4670..3685acfdd7 100644
--- a/components/printers/sample/frmselprinter.pas
+++ b/components/printers/sample/frmselprinter.pas
@@ -97,11 +97,11 @@ begin
poReverseLandscape : AddInfo('Orientation','ReverseLandscape');
poReversePortrait :AddInfo('Orientation','ReversePortrait');
end;
- AddInfo('XDPI',IntToStr(XDPI));
- AddInfo('YDPI',IntToStr(YDPI));
+ AddInfo('XDPI',IntToStr(XDPI)+' dpi');
+ AddInfo('YDPI',IntToStr(YDPI)+' dpi');
AddInfo('Copies',IntToStr(Copies));
- AddInfo('PageHeight',IntToStr(PageHeight));
- AddInfo('PageWidth',IntToStr(PageWidth));
+ AddInfo('PageHeight',IntToStr(PageHeight)+' dots (printable size)');
+ AddInfo('PageWidth',IntToStr(PageWidth)+' dots (printable size)');
case PrinterType of
ptLocal: AddInfo('PrinterType','Local');
ptNetWork: AddInfo('PrinterType','Network');
@@ -168,6 +168,7 @@ begin
{$ELSE}
ShowMessage('Printer.AdvancedProperties is not yet implemented for this platform');
{$ENDIF}
+ UpdatePrinterInfo;
end;
procedure TForm1.Button7Click(Sender: TObject);
diff --git a/components/printers/sample/selectprinter.lpi b/components/printers/sample/selectprinter.lpi
index 2f1f35df43..2e5ee605a2 100644
--- a/components/printers/sample/selectprinter.lpi
+++ b/components/printers/sample/selectprinter.lpi
@@ -1,60 +1,21 @@
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -62,7 +23,7 @@
-
+
@@ -74,11 +35,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -110,26 +94,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/printers/win32/winprinters.inc b/components/printers/win32/winprinters.inc
index 621b3ce07d..b7b0ae5f04 100644
--- a/components/printers/win32/winprinters.inc
+++ b/components/printers/win32/winprinters.inc
@@ -1,8 +1,24 @@
+{%MainUnit ../osprinters.pas}
{**************************************************************
Implementation for winprinter
***************************************************************}
Uses WinUtilPrn, InterfaceBase, Win32Int, LCLIntf,WinVer;
+// todo: this ^ is a mess: mixed WinUtilPrn/Windows units clean...
+
+// todo: this should be a method, cant be atm because mixed units ^
+function GetCurrentDevMode(var DM:PDeviceMode): boolean;
+var
+ PDev: TPrinterDevice;
+begin
+ result := false;
+ if (Printer.Printers.Count>0) then
+ begin
+ PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
+ DM := PDev.DevMode;
+ result := DM<>nil;
+ end;
+end;
{ TWinPrinter }
@@ -69,12 +85,13 @@ begin
if (fLastHandleType=0) and (Printers.Count>0) then
begin
PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
+
fDC:=CreateIC(PChar(PDev.Driver),PChar(PDev.Device),
- PChar(PDev.Port),@PDev.DevMode);
+ PChar(PDev.Port),PDev.DevMode);
if fDC=0 then
fDC:=CreateIC(PChar('WINSPOOL'),PChar(PDev.Device),
- PChar(PDev.Port),@PDev.DevMode);
+ PChar(PDev.Port),PDev.DevMode);
if fDC=0 then
raise EPrinter.Create(Format('Invalid printer (DC=%d Driver=%s Device=%s Port=%s)',[fDC,Pdev.Driver,PDev.Device,PDev.Port]));
@@ -93,16 +110,17 @@ begin
PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
try
- //Device is only 32 chars long, if the Printername or share is longer than 32 chars, this will return 0
- fDC:=CreateDC(nil,PChar(Printers[PrinterIndex]),nil,@PDev.DevMode);
+ //Device is only 32 chars long,
+ //if the Printername or share is longer than 32 chars, this will return 0
+ fDC:=CreateDC(nil,PChar(Printers[PrinterIndex]),nil, PDev.DevMode);
if fDC=0 then
- fDC:=CreateDC(PChar('WINSPOOL'),PChar(Printers[PrinterIndex]),nil,@PDev.DevMode);
+ fDC:=CreateDC(PChar('WINSPOOL'),PChar(Printers[PrinterIndex]),nil,PDev.DevMode);
{Workaround (hack) for Lexmark 1020 JetPrinter (Mono)}
if fDC=0 then
- fDC:=CreateDC(nil,PChar(PDev.Driver),nil,@PDev.DevMode);
+ fDC:=CreateDC(nil,PChar(PDev.Driver),nil, PDev.DevMode);
if fDC=0 then
- fDC:=CreateDC(pChar('WINSPOOL'),PChar(PDev.Driver),nil,@PDev.DevMode);
+ fDC:=CreateDC(pChar('WINSPOOL'),PChar(PDev.Driver),nil,PDev.DevMode);
except on E:Exception do
raise EPrinter.Create(Format('CreateDC exception: %s (LastError : %s,DC=%d Driver="%s" Device="%s" Port="%s")',[E.Message,SysErrorMessage(GetLastError),fDC,Pdev.Driver,Printers[PrinterIndex],PDev.Port]));
@@ -129,6 +147,41 @@ begin
fLastHandleType:=0;
end;
+
+// Based on MS Article Q167345
+procedure TWinPrinter.UpdateDevMode;
+var
+ PDev: TPrinterDevice;
+ dwRet: Integer;
+begin
+ // now we have a right FPrinterHandle, get current printer settings
+ PDev := TPrinterDevice(Printers.Objects[PrinterIndex]);
+
+ // allocate a new Devmode
+ if (Pdev.DevMode=nil) then begin
+
+ // 1. Determine the required size of the buffer from the device,
+ // and then allocate enough memory for it.
+ PDev.DevModeSize:=DocumentProperties(0, FPrinterHandle, pchar(PDev.Name),
+ nil, nil, 0);
+ if PDev.DevModeSize<=0 then begin
+ // error
+ exit;
+ end;
+ GetMem(PDev.DevMode, PDev.DevModeSize);
+
+ // 2. Ask the device driver to initialize the DEVMODE buffer with
+ // the default settings.
+ dwRet := DocumentProperties(0, FPrinterHandle, pchar(Pdev.Name),
+ PDev.DevMode, nil, DM_OUT_BUFFER);
+ if (dwRet<>IDOK) then begin
+ FreeMem(PDev.DevMode);
+ PDev.DevMode:=nil;
+ end;
+ end;
+
+end;
+
procedure TWinPrinter.DoBeginDoc;
var Inf: TDocInfo;
begin
@@ -184,6 +237,7 @@ Var Flags : DWORD;
i : Integer;
DefaultPrinter : array[0..79] of Char;
PDev : TPrinterDevice;
+ TmpDevMode : PDeviceMode;
begin
Level:=5; //Compatible with all Win32 versions
DefaultPrinter:='';
@@ -221,6 +275,7 @@ begin
if Needed<>0 then
begin
GetMem(Buffer,Needed);
+ Fillchar(Buffer^, Needed, 0);
try
//Enumerate Printers
if EnumPrinters(Flags,nil,Level,Buffer,Needed,Needed,PrtCount) then
@@ -234,10 +289,17 @@ begin
PDev.Name :=PPRINTER_INFO_2(InfoPrt)^.pPrinterName;
PDev.Driver:=PPRINTER_INFO_2(InfoPrt)^.pDriverName;
PDev.Port :=PPRINTER_INFO_2(InfoPrt)^.pPortName;
- if PPRINTER_INFO_2(InfoPrt)^.PDevMode <> nil then begin
- PDev.DevMode:=PPRINTER_INFO_2(InfoPrt)^.PDevMode^;
- PDev.Device:=PDev.DevMode.dmDeviceName;
- PDev.DefaultPaper:=PDev.DevMode.dmPaperSize;
+ TmpDevMode :=PPRINTER_INFO_2(InfoPrt)^.pDevMode;
+ if TmpDevMode<>nil then begin
+ // the devmode structure obtained this way have two problems
+ // 1. It's not the full devmode, because it doesn't have
+ // the private info
+ // 2. It's not initialized with the current settings and
+ // have not extra settings at all.
+ //
+ // PDev.DevMode:=PPRINTER_INFO_2(InfoPrt)^.PDevMode^;
+ PDev.Device:= TmpDevMode^.dmDeviceName; //PDev.DevMode.dmDeviceName;
+ PDev.DefaultPaper:=TmpDevMode^.dmPaperSize; //PDev.DevMode.dmPaperSize;
end
else begin
PDev.Device:='';
@@ -326,19 +388,17 @@ begin
end;
function TWinPrinter.DoGetPaperName: string;
-var i : Integer;
- PDev : TPrinterDevice;
+var
+ i : Integer;
+ dm : PDeviceMode;
begin
Result:=inherited DoGetPaperName;
-
- if (Printers.Count>0) then
- begin
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
-
- i:=PaperSize.SupportedPapers.IndexOfObject(TObject(ptrint(PDev.Devmode.dmPaperSize)));
- if i<>-1 then
- Result:=PaperSize.SupportedPapers.Strings[i];
- end;
+ if GetCurrentDevMode(dm) then
+ with PaperSize.SupportedPapers do begin
+ i := IndexOfObject(TObject(ptrInt(dm^.dmPaperSize)));
+ if i>=0 then
+ result := PaperSize.SupportedPapers[i];
+ end;
end;
function TWinPrinter.DoGetDefaultPaperName: string;
@@ -359,22 +419,14 @@ end;
procedure TWinPrinter.DoSetPaperName(aName: string);
var i : Integer;
- PDev : TPrinterDevice;
- j : SHORT;
+ dm : PDeviceMode;
begin
inherited DoSetPaperName(aName);
-
- if (Printers.Count>0) then
- begin
-
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
-
+ if GetCurrentDevMode(dm) then begin
i:=PaperSize.SupportedPapers.IndexOf(aName);
- if i<>-1 then
- begin
+ if i<>-1 then begin
ClearDC;
- j:=SHORT(ptrint(PaperSize.SupportedPapers.Objects[i]));
- PDev.DevMode.dmPaperSize:=j;
+ dm^.dmPaperSize := SHORT(ptrint(PaperSize.SupportedPapers.Objects[i]));
end;
end;
end;
@@ -388,20 +440,50 @@ begin
if (Printers.Count>0) then
begin
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
+ // Information for physical sizes can be obtained for any paper supported
+ // by the printer, the same is not true for printable paper size, this can
+ // be obtained only(?) for currently selected paper.
+ //
+ if DoGetPaperName=AName then begin
+ SetDC;
+ with aPaperRC.PhysicalRect do begin
+ Left :=0;
+ Top :=0;
+ Right :=Windows.GetDeviceCaps(fDC, PHYSICALWIDTH);
+ Bottom:=Windows.GetDeviceCaps(fDC, PHYSICALHEIGHT);
+ end;
+ with aPaperRC.WorkRect do begin
+ Left :=Windows.GetDeviceCaps(fDC, PHYSICALOFFSETX);
+ Top :=Windows.GetDeviceCaps(fDC, PHYSICALOFFSETY);
+ Right :=Left + Windows.GetDeviceCaps(fDC, HORZRES);
+ Bottom:=Bottom + Windows.GetDeviceCaps(fDC, VERTRES);
+ end;
+ end else begin
+ // for other papers return at least the physical size
+ // note: old implementation was using DeviceCapabilities function with
+ // index DC_PAPERSIZE, unfortunately this returns dimensions in
+ // tenths of millimeter which is wrong, we need points (not font
+ // points, but printer "pixels" at current resolution).
+ //
+ PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
- //Retreive the Width and Height of aName paper
- FillChar(ArSizes,SizeOf(ArSizes),0);
- NSize:=DeviceCapabilities(PChar(Pdev.Name),PChar(PDev.Port),
- DC_PAPERSIZE,@ArSizes,nil);
- i:=PaperSize.SupportedPapers.IndexOf(aName);
- if (i>=0) and (i0) then
- begin
- aPaperRc.PhysicalRect:=Classes.Rect(0,0,ArSizes[i].X,ArSizes[i].Y);
- aPaperRc.WorkRect:=Classes.Rect(0,0,ArSizes[i].X,ArSizes[i].Y);
-
- Result:=1;
+ //Retreive the Width and Height of aName paper
+ FillChar(ArSizes,SizeOf(ArSizes),0);
+ NSize:=DeviceCapabilities(PChar(Pdev.Name),PChar(PDev.Port),
+ DC_PAPERSIZE,@ArSizes,nil);
+ i:=PaperSize.SupportedPapers.IndexOf(aName);
+ if (i>=0) and (i0) then
+ begin
+ aPaperRc.PhysicalRect:=Classes.Rect(0,0,ArSizes[i].X,ArSizes[i].Y);
+ with aPaperRC.PhysicalRect do begin
+ // convert from tenths of millimeter to points
+ Right := round(Right * XDPI / 254);
+ Bottom := round(Bottom* YDPI / 254);
+ end;
+ aPaperRc.WorkRect := aPaperRC.PhysicalRect;
+ end;
end;
+ Result:=1;
end;
end;
@@ -418,68 +500,57 @@ begin
PDev:=TPrinterDevice(Printers.Objects[i]);
if fPrinterHandle<>0 then
ClosePrinter(fPrinterHandle);
-
- if not OpenPrinter(PChar(PDev.Name),fPrinterHandle,nil) then
- raise EPrinter.CreateFmt('OpenPrinter exception : %s',[SysErrorMessage(GetlastError)]);
+ if not OpenPrinter(PChar(PDev.Name),fPrinterHandle, nil) then
+ raise EPrinter.CreateFmt('OpenPrinter exception : %s',[SysErrorMessage(GetlastError)])
+ else
+ UpdateDevMode;
Result:=i;
end;
end;
function TWinPrinter.DoGetCopies: Integer;
-var PDev : TPrinterDevice;
+var
+ dm: PDeviceMode;
begin
Result:=inherited DoGetCopies;
-
- if (Printers.Count>0) then
- begin
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
-
- if PDev.DevMode.dmCopies<>0 then
- Result:=PDev.DevMode.dmCopies;
+ if GetCurrentDevMode(dm) then begin
+ if dm^.dmCopies<>0 then
+ result := dm^.dmCopies;
end;
end;
procedure TWinPrinter.DoSetCopies(aValue: Integer);
-var PDev : TPrinterDevice;
+var
+ dm: PDeviceMode;
begin
inherited DoSetCopies(aValue);
-
- if (Printers.Count>0) and (aValue>0) then
- begin
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
-
+ if (AValue>0) and GetCurrentDevMode(dm) then begin
ClearDC;
- PDev.DevMode.dmCopies:=SHORT(aValue);
+ dm^.dmCopies := SHORT(aValue)
end;
end;
function TWinPrinter.DoGetOrientation: TPrinterOrientation;
-var PDev : TPrinterDevice;
+var
+ dm: PDeviceMode;
begin
Result:=inherited DoGetOrientation;
-
- if (Printers.Count>0) then
- begin
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
-
- Case PDev.DevMode.dmOrientation of
- DMORIENT_PORTRAIT : Result:=poPortrait;
- DMORIENT_LANDSCAPE : Result:=poLandscape;
+ if GetCurrentDevMode(dm) then begin
+ case dm^.dmOrientation of
+ DMORIENT_PORTRAIT : result:=poPortrait;
+ DMORIENT_LANDSCAPE: result:=poLandscape;
end;
end;
end;
procedure TWinPrinter.DoSetOrientation(aValue: TPrinterOrientation);
-var PDev : TPrinterDevice;
+var
+ dm: PDeviceMode;
begin
inherited DoSetOrientation(aValue);
-
- if (Printers.Count>0) then
- begin
- PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
-
+ if GetCurrentDevMode(dm) then begin
ClearDC;
- PDev.DevMode.dmOrientation:=Win32Orientations[aValue];
+ dm^.dmOrientation := Win32Orientations[aValue];
end;
end;
@@ -566,14 +637,23 @@ begin
if (Printers.Count>0) then
begin
PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
- Count := DeviceCapabilities(PChar(Pdev.Name),PCHar(PDev.Port),DC_COPIES,nil,@PDev.DevMode);
- Result := (Count > 1);
- end;
+ Count := DeviceCapabilities(PChar(Pdev.Name),PCHar(PDev.Port),DC_COPIES,nil,PDev.DevMode);
+ Result := (Count>1);
+ end;
end;
procedure TWinPrinter.AdvancedProperties;
+var
+ PDev: TPrinterDevice;
begin
- PrinterProperties(TWin32WidgetSet(WidgetSet).AppHandle,fPrinterHandle);
+ PDev:=TPrinterDevice(Printers.Objects[PrinterIndex]);
+ DocumentProperties(
+ TWin32WidgetSet(WidgetSet).AppHandle,
+ FPrinterHandle,
+ pchar(PDev.Name),
+ Pdev.DevMode, Pdev.DevMode,
+ DM_OUT_BUFFER or DM_IN_BUFFER or DM_IN_PROMPT);
+ //PrinterProperties(TWin32WidgetSet(WidgetSet).AppHandle,fPrinterHandle)
end;
initialization
diff --git a/components/printers/win32/winprinters_h.inc b/components/printers/win32/winprinters_h.inc
index 8e204d1e6a..322b41d4bd 100644
--- a/components/printers/win32/winprinters_h.inc
+++ b/components/printers/win32/winprinters_h.inc
@@ -1,3 +1,4 @@
+{%MainUnit ../osprinters.pas}
{
Author: Olivier Guilbaud
@@ -41,7 +42,7 @@ Type
procedure SetIC;
procedure SetDC;
procedure ClearDC;
-
+ procedure UpdateDevMode;
protected
//function GetDefaultPrinter : String;
diff --git a/components/printers/win32/winprndialogs.inc b/components/printers/win32/winprndialogs.inc
index 2bf31bac79..5331472629 100644
--- a/components/printers/win32/winprndialogs.inc
+++ b/components/printers/win32/winprndialogs.inc
@@ -1,3 +1,4 @@
+{%MainUnit ../printersdlgs.pp}
Uses
Windows,WinUtilPrn, InterfaceBase, Win32Int, LCLIntf,LCLType,WinVer;
@@ -20,36 +21,26 @@ begin
if Printer.Printers.Count>0 then
begin
FillChar(lpp,SizeOf(lpp),0);
- with lpp do
- begin
+ with lpp do begin
lStructSize:=SizeOf(lpp);
hInstance:=LCLType.HInstance;
Flags := PSD_MARGINS;
hWndOwner:=TWin32WidgetSet(WidgetSet).AppHandle;
rtMargin := fMargins;
PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
- Size := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_SIZE,nil,nil);
- Extra := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_EXTRA,nil,nil);
- Fields := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_FIELDS,nil,nil);
- DeviceMode:=GlobalAlloc(GHND,Size + Extra);
+ // Pdev.DevMode has the required size, just copy to the global memory
+ DeviceMode:=GLobalAlloc(GHND, PDev.DevModeSize);
try
- DevMode:=PDeviceMode(GlobalLock(DeviceMode));
- try
- CopyMemory(DevMode,@PDev.DevMode,SizeOf(PDev.DevMode));
- DevMode^.dmSize := Word(Size);
- DevMode^.dmDriverExtra := Word(Extra);
- DevMode^.dmFields := Fields;
- finally
- GlobalUnLock(DeviceMode);
- end;
-
- hDevMode:= DeviceMode;
- if PageSetupDlg(lpp) then
- begin
- St:='';
- //Change Selected printer
- if lpp.hDevNames<>0 then
- begin
+ DevMode:=PDeviceMode(GlobalLock(DeviceMode));
+ try
+ CopyMemory(DevMode, PDev.DevMode, Pdev.DevModeSize);
+ finally
+ GlobalUnlock(DeviceMode);
+ end;
+ hDevMode:=DeviceMode;
+ if PageSetupDlg(Lpp) then begin
+ St :='';
+ if Lpp.HdevNames<>0 then begin
DevNames:=PDevNames(GlobalLock(lpp.hDevNames));
try
St:=PChar(DevNames)+DevNames^.wDeviceOffset;
@@ -59,11 +50,12 @@ begin
GlobalFree(lpp.hDevNames);
end;
end;
-
+
Result:=True;
- if (Flags and PSD_INHUNDREDTHSOFMILLIMETERS)>0 then fUnits := unMM
+ if (Flags and PSD_INHUNDREDTHSOFMILLIMETERS)>0 then
+ fUnits := unMM
else
- fUnits := unInch;
+ fUnits := unInch;
fMargins := rtMargin;
if lpp.hDevMode<>0 then
@@ -72,10 +64,7 @@ begin
try
//Set the properties for the selected printer
PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
- CopyMemory(@PDev.DevMode,DevMode,sizeof(Pdev.DevMode));
- PDev.DevMode.dmSize := SizeOf(PDev.DevMode);
- PDev.DevMode.dmDriverExtra := 0;
- PDev.DevMode.dmPaperSize := DevMode^.dmPaperSize;
+ CopyMemory(PDev.DevMode,DevMode,PDev.DevModeSize);
finally
GlobalUnlock(lpp.hDevMode);
end;
@@ -113,25 +102,18 @@ begin
hInstance:=LCLType.HInstance;
Flags:= PD_PRINTSETUP or PD_RETURNDC;
hWndOwner:=TWin32WidgetSet(WidgetSet).AppHandle;
-
PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
- Size := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_SIZE,nil,nil);
- Extra := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_EXTRA,nil,nil);
- Fields := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_FIELDS,nil,nil);
- DeviceMode:=GlobalAlloc(GHND,Size + Extra);
+ // Pdev.DevMode has the required size, just copy to the global memory
+ DeviceMode:=GlobalAlloc(GHND, PDev.DevModeSize);
try
- DevMode:=PDeviceMode(GlobalLock(DeviceMode));
- try
- CopyMemory(DevMode,@PDev.DevMode,SizeOf(PDev.DevMode));
- DevMode^.dmSize := Word(Size);
- DevMode^.dmDriverExtra := Word(Extra);
- DevMode^.dmFields := Fields;
- finally
- GlobalUnLock(DeviceMode);
- end;
-
- hDevMode:= DeviceMode;
- if PrintDlg(lpp) then
+ DevMode:=PDeviceMode(GlobalLock(DeviceMode));
+ try
+ CopyMemory(DevMode, Pdev.DevMode, Pdev.DevModeSize);
+ finally
+ GlobalUnlock(DeviceMode);
+ end;
+ hDevMode := DeviceMode;
+ if PrintDlg(lpp) then
begin
St:='';
//Change Selected printer
@@ -155,10 +137,7 @@ begin
try
//Set the properties for the selected printer
PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
- CopyMemory(@PDev.DevMode,DevMode,sizeof(Pdev.DevMode));
- PDev.DevMode.dmSize := SizeOf(PDev.DevMode);
- PDev.DevMode.dmDriverExtra := 0;
- PDev.DevMode.dmPaperSize := Devmode^.dmPaperSize;
+ CopyMemory(PDev.DevMode,DevMode,PDev.DevModeSize);
TWinPrinter(Printer).Handle := hDC;
finally
GlobalUnlock(lpp.hDevMode);
@@ -210,30 +189,25 @@ begin
if not (poWarning in Options) then Flags := Flags or PD_NOWARNING;
hWndOwner:=TWin32WidgetSet(WidgetSet).AppHandle;
-
PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
- Size := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_SIZE,nil,nil);
- Extra := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_EXTRA,nil,nil);
- Fields := DeviceCapabilities(PChar(PDev.Name),PChar(PDev.Port),DC_FIELDS,nil,nil);
- DeviceMode:=GlobalAlloc(GHND,Size + Extra);
+ // Pdev.DevMode has the required size, just copy to the global memory
+ DeviceMode:=GlobalAlloc(GHND, PDEV.DevModeSize);
try
- DevMode:=PDeviceMode(GlobalLock(DeviceMode));
- try
- CopyMemory(DevMode,@PDev.DevMode,SizeOf(PDev.DevMode));
- DevMode^.dmSize := Word(Size);
- DevMode^.dmDriverExtra := Word(Extra);
- DevMode^.dmFields := Fields;
- finally
- GlobalUnLock(DeviceMode);
- end;
-
- hDevMode:= DeviceMode;
- nCopies:= Word(Copies);
- nFromPage := Word(FromPage);
- nToPage := Word(ToPage);
- nMinPage := Word(MinPage);
- nMaxPage := Word(MaxPage);
- if PrintDlg(lpp) then
+ DevMode:=PDeviceMode(GlobalLock(DeviceMode));
+ try
+ CopyMemory(DevMode, PDev.DevMode, PDev.DevModeSize);
+ finally
+ GlobalUnlock(DeviceMode);
+ end;
+
+ hDevMode:= DeviceMode;
+ nCopies:= Word(Copies);
+ nFromPage := Word(FromPage);
+ nToPage := Word(ToPage);
+ nMinPage := Word(MinPage);
+ nMaxPage := Word(MaxPage);
+
+ if PrintDlg(lpp) then
begin
St:='';
//Change Selected printer
@@ -250,25 +224,24 @@ begin
end;
Result:=True;
-
-
+
if lpp.hDevMode<>0 then
begin
DevMode:=PDeviceMode(GlobalLock(lpp.hDevMode));
try
//Set the properties for the selected printer
PDev:=TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]);
- CopyMemory(@PDev.DevMode,DevMode,sizeof(Pdev.DevMode));
- PDev.DevMode.dmSize := SizeOf(PDev.DevMode);
- PDev.DevMode.dmDriverExtra := 0;
+ CopyMemory(PDev.DevMode,DevMode,PDev.DevModeSize);
+
if Printer.PaperSize.SupportedPapers.IndexOfObject(TObject(ptrint(DevMode^.dmPaperSize))) <> -1
then
- PDev.DevMode.dmPaperSize := DevMode^.dmPaperSize
+ PDev.DevMode^.dmPaperSize := DevMode^.dmPaperSize
else
- PDev.DevMode.dmPaperSize := PDev.DefaultPaper;
- if nCopies=1 then Copies := DevMode^.dmCopies
+ PDev.DevMode^.dmPaperSize := PDev.DefaultPaper;
+ if nCopies=1 then
+ Copies := DevMode^.dmCopies
else
- Copies := nCopies;
+ Copies := nCopies;
Printer.Copies := Copies;
TWinPrinter(Printer).Handle := hDC;
finally
diff --git a/components/printers/win32/winutilprn.pas b/components/printers/win32/winutilprn.pas
index 215e57ef7f..b8ca72e5b6 100644
--- a/components/printers/win32/winutilprn.pas
+++ b/components/printers/win32/winutilprn.pas
@@ -148,15 +148,21 @@ type
Type
+
+ { TPrinterDevice }
+
TPrinterDevice = class
+ public
Name : String;
Driver : String;
Device : String;
Port : String;
DefaultPaper : Short;
-
- DevMode: TDeviceMode;
+
+ DevMode: PDeviceMode;
+ DevModeSize: Integer;
+ destructor destroy; override;
end;
@@ -288,6 +294,16 @@ function AdvancedDocumentProperties(
pDevModeInput : PDeviceMode // original device mode data
): Longint; stdcall; external LibWinSpool name 'AdvancedDocumentPropertiesA';
+
+function DocumentProperties(
+ hWnd :HWND; // handle to parent window
+ hPrinter :THandle; // handle to printer object
+ pDeviceName :Pchar; // device name
+ pDevModeOutput:PdeviceMode; // modified device mode
+ pDevModeInput :PdeviceMode; // original device mode
+ fMode :DWORD // mode options
+ ): Longint; stdcall; external LibWinSpool name 'DocumentPropertiesA';
+
function DeviceCapabilities(pDevice, pPort: PChar; fwCapability: Word; pOutput: PChar;
DevMode: PDeviceMode): Integer; stdcall; external LibWinSpool name 'DeviceCapabilitiesA';
@@ -305,8 +321,20 @@ function EndDoc(DC: HDC): Integer; stdcall; external 'gdi32.dll' name 'EndDoc';
function StartPage(DC: HDC): Integer; stdcall; external 'gdi32.dll' name 'StartPage';
function EndPage(DC: HDC): Integer; stdcall; external 'gdi32.dll' name 'EndPage';
function AbortDoc(DC: HDC): Integer; stdcall; external 'gdi32.dll' name 'AbortDoc';
+function GlobalFree(HMem: HGlobal): HGlobal; stdcall; external 'kernel32.dll' name 'GlobalFree';
implementation
+{ TPrinterDevice }
+
+destructor TPrinterDevice.destroy;
+begin
+ if DevMode<>nil then begin
+ FreeMem(DevMode);
+ DevMode:=nil;
+ end;
+ inherited destroy;
+end;
+
end.
diff --git a/lcl/printers.pas b/lcl/printers.pas
index c3e0201e68..8ad6a6b014 100644
--- a/lcl/printers.pas
+++ b/lcl/printers.pas
@@ -444,18 +444,23 @@ begin
Result:=DoGetOrientation;
end;
+// Returns the height in points (pixels) of printable area
function TPrinter.GetPageHeight: Integer;
begin
Result:=0;
if (Printers.Count>0) then
- Result:=PaperSize.PaperRect.PhysicalRect.Bottom;
+ with PaperSize.PaperRect.WorkRect do
+ Result:=Bottom-Top;
end;
+// Returns the width in points (pixels) of the printable area
function TPrinter.GetPageWidth: Integer;
begin
Result:=0;
if (Printers.Count>0) then
- Result:=PaperSize.PaperRect.PhysicalRect.Right;
+ with PaperSize.PaperRect.WorkRect do
+ // PageWidth is the size in "pixels" of the printable area
+ Result:=Right-Left;
end;
function TPrinter.GetPaperSize: TPaperSize;
@@ -500,7 +505,6 @@ begin
Result:=1;
end;
-
//Set the copies numbers
procedure TPrinter.SetCopies(AValue: Integer);
begin