fixed printer related problems (paper sizes, printouts now use current settings, advanced settings preserved after dialogs) in windows

git-svn-id: trunk@9448 -
This commit is contained in:
jesus 2006-06-19 08:24:58 +00:00
parent 0d67131d5f
commit aac0598b39
10 changed files with 358 additions and 297 deletions

View File

@ -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 :

View File

@ -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

View File

@ -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
]);

View File

@ -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);

View File

@ -1,60 +1,21 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="/"/>
<PathDelim Value="\"/>
<Version Value="5"/>
<General>
<Flags>
<SaveClosedFiles Value="False"/>
<SaveOnlyProjectUnits Value="True"/>
</Flags>
<SessionStorage Value="None"/>
<MainUnit Value="0"/>
<IconPath Value="./"/>
<TargetFileExt Value=".exe"/>
<Title Value="selectprinter"/>
<ActiveEditorIndexAtStart Value="0"/>
</General>
<LazDoc Paths=""/>
<Units Count="4">
<Unit0>
<CursorPos X="19" Y="15"/>
<Filename Value="selectprinter.lpr"/>
<IsPartOfProject Value="True"/>
<TopLine Value="1"/>
<UnitName Value="selectprinter"/>
<UsageCount Value="154"/>
</Unit0>
<Unit1>
<CursorPos X="34" Y="109"/>
<EditorIndex Value="0"/>
<Filename Value="frmselprinter.pas"/>
<ComponentName Value="Form1"/>
<IsPartOfProject Value="True"/>
<Loaded Value="True"/>
<ResourceFilename Value="frmselprinter.lrs"/>
<TopLine Value="81"/>
<UnitName Value="frmselprinter"/>
<UsageCount Value="154"/>
</Unit1>
<Unit2>
<CursorPos X="10" Y="296"/>
<Filename Value="C:/lazarus/components/PRINTERS/WIN32/winprndialogs.inc"/>
<IsPartOfProject Value="True"/>
<TopLine Value="1"/>
<UnitName Value="text"/>
<UsageCount Value="100"/>
</Unit2>
<Unit3>
<CursorPos X="1" Y="1"/>
<Filename Value="C:/lazarus/components/PRINTERS/LINUX/cupsprndialogs.inc"/>
<IsPartOfProject Value="True"/>
<TopLine Value="1"/>
<UnitName Value="text"/>
<UsageCount Value="100"/>
</Unit3>
</Units>
<PublishOptions>
<Version Value="2"/>
<DestinationDirectory Value="$(TestDir)\publishedproject\"/>
<IgnoreBinaries Value="False"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
@ -62,7 +23,7 @@
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<RequiredPackages Count="2">
@ -74,11 +35,34 @@
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="4">
<Unit0>
<Filename Value="selectprinter.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="selectprinter"/>
</Unit0>
<Unit1>
<Filename Value="frmselprinter.pas"/>
<ComponentName Value="Form1"/>
<IsPartOfProject Value="True"/>
<ResourceFilename Value="frmselprinter.lrs"/>
<UnitName Value="frmselprinter"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\..\..\..\..\lazarus\components\PRINTERS\WIN32\winprndialogs.inc"/>
<IsPartOfProject Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\..\..\..\..\..\..\lazarus\components\PRINTERS\LINUX\cupsprndialogs.inc"/>
<IsPartOfProject Value="True"/>
</Unit3>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="5"/>
<PathDelim Value="\"/>
<SearchPaths>
<SrcPath Value="$(LazarusDir)/lcl/;$(LazarusDir)/lcl/interfaces/$(LCLWidgetType)/"/>
<SrcPath Value="$(LazarusDir)\lcl\;$(LazarusDir)\lcl\interfaces\$(LCLWidgetType)\"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
@ -110,26 +94,4 @@
</Other>
<CompileReasons Run="False"/>
</CompilerOptions>
<Debugging>
<Watches Count="6">
<Item1>
<Expression Value="lpp.nCopies"/>
</Item1>
<Item2>
<Expression Value="DevMode^.dmCopies"/>
</Item2>
<Item3>
<Expression Value="PDev.DevMode.dmDriverExtra"/>
</Item3>
<Item4>
<Expression Value="AName"/>
</Item4>
<Item5>
<Expression Value="Pdev.name"/>
</Item5>
<Item6>
<Expression Value="pdev.name"/>
</Item6>
</Watches>
</Debugging>
</CONFIG>

View File

@ -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 (i<NSize) and (NSize<>0) 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 (i<NSize) and (NSize<>0) 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

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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