Recent

Author Topic: [SOLVED] Setting printer properties in PrintDialog  (Read 21985 times)

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: Setting printer properties in PrintDialog
« Reply #15 on: June 01, 2018, 10:44:34 am »
Am I a fool if I think TPrinter must have some other properties like "ColorMode" or "DuplexMode"?
To answer your question literally: Yes, but no offense.  ;)

I think the philosophy is that TPrinter supports only the minimum features which all (or most?) printers provide, such as page orientation, or paper size. Many models, however, have more features, like duplex mode. But the print dialogs are taken from the OS, they are no Lazarus forms, Lazarus has no possibility to change them (well, some hacker methods certainly exist). In principle, access to the additional features in the print dialogs can be made via OS-specific calls, but Lazarus does not provide this in TPrinter because it must be platform-independent and nobody, so far, has taken the burden to re-write TPrinter using a widgetset technology like in the LCL.

If you want the print dialogs to show only those options supported by your program you must write your own dialogs. Apply the parameters supported by TPrinter to TPrinter directly. Accomplish other features in your application - I am thinking of color/grayscale mode here: if the user wants a grayscale print-out of an image by checking the grayscale box in the print dialog, then convert the bitmap to grayscale before sending it to the printer- you now can read the grayscale option from the dialog because it is your own form, not that of the OS.

If you want features which can be accomplished by hardware only (such as duplex print) you return to the main problem again: How do you know that the user's printer can operate in duplex? Since Lazarus does not support platform-independent access to all properties or the printer driver you will have a hard life in squeezing everything out of the printer in the most general way.

RayoGlauco

  • Full Member
  • ***
  • Posts: 174
  • Beers: 1567
Re: Setting printer properties in PrintDialog
« Reply #16 on: June 01, 2018, 11:04:34 am »
Thanks, wp.
Now I am more clear about what to do.
I will design my own PrintDialog, including only the options that I can really handle.
« Last Edit: June 01, 2018, 11:07:54 am by RayoGlauco »
To err is human, but to really mess things up, you need a computer.

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Setting printer properties in PrintDialog
« Reply #17 on: June 01, 2018, 08:03:08 pm »
@wp: that is Delphi code however, The GetPrinter function can be adopted from the API call of GetPrinter


 I do have a couple of apps in laz that uses the printer and I did do something with some API code to get things
working...


 I'll take a look to see what it was I did...

The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Setting printer properties in PrintDialog
« Reply #18 on: June 01, 2018, 09:27:50 pm »
Ok,  I have had a look at an app we use at work that I converted from Delphi over laz..

I use the "DocumentProperties" along with info from the Printers Unit.

I do not know why "Printers" does not support the SetPrinter and GetPrinter as did/does Delphi. On top of all
that, the DocumentProperties API is not defined in the windows unit but the records are? Which is most likely the
reason I had to an Define of it in my app..

 For now you can use the DocumentProperties function, follow the guide lines laid out via MS.

 There are many examples out there to do this with Lazarus and many posted examples of using this API with Delphi which
should compile.
The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: Setting printer properties in PrintDialog
« Reply #19 on: June 01, 2018, 10:12:49 pm »
You want to say that the DocumentProperties function (which is declared in unit WinUtilPrn) is the way to access details on the print dialogs? As usual, the MSN  page on DocumentProperties (https://msdn.microsoft.com/en-us/library/windows/desktop/dd183576(v=vs.85).aspx) is hard reading...

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Setting printer properties in PrintDialog
« Reply #20 on: June 02, 2018, 12:41:09 am »
The DocumentProperties can but does not need to, present a dialog to the user.

Its in the parameters.

 fMode parameter indicates what to do..

  DM_IN_PROMPT will present a setup dialog to the user.
 
  DM_IN_BUFFER will read the current printers DEVMODE record which contains all of the standard settings, plus duplex mode

  DM_OUT_BUFFER will output this Record back to the print driver

  If you set this parameter to 0 then what happens is the function will return the size of memory needed to
contain a DEVMODE record.

  This is needed first to make sure you have enough space because printer venders will add to the end.

 So first call is 0 for this fMode.

 So after the initial call to determine needed space,  you then call it again with DM_IN_BUFFER and pass it the pointer
of the buffer to the function.
  This will fill the DEVMODE record

Personally, I think the TPrinter Class should provide a Property that you can read and write this DEVMODE and if for some
reason other targets can't provide this, have it return a blank or fill in as much of it as possible.

EDIT:

 Forgot to mention , the pDevModeInput will point to the incoming DEVMODE and the pDevModeOutput will be another
DEVMODE that is modified and gets sent to the printer when you do the DM_OUT....

 so you simply move a copy of the incoming over to the out-going and make your changes to the out going..

« Last Edit: June 02, 2018, 12:47:51 am by jamie »
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Setting printer properties in PrintDialog
« Reply #21 on: June 02, 2018, 02:55:49 am »
Something I came up with as an example...
I don't have a printer at this location where I can test the duplex mode.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var
  3.   pDev:pDevmodeW; // Made a boo boo bere, needed to use the (W) version..
  4.   DevSize :integer;
  5.   PrnH:Thandle;
  6.   NS :WideString;
  7. begin
  8.    NS := Printer.PrinterName+#0#0;
  9.  If  OpenPrinterW(@NS[1],@PrnH,nil) Then
  10.    Begin
  11.     DevSize := DocumentPropertiesW(Handle,PrnH,@NS[1],nil,nil,0);
  12.     GetMem(pDEV,DevSize);
  13.     DocumentPropertiesW(Handle, PrnH,@NS[1],LPDEVMODEW(pDev), nil, DM_OUT_BUFFER);
  14.     If pDev^.dmFields And DM_DUPLEX <> 0 Then   //if it supports it, try a Duplex change.
  15.       Begin
  16.        pDev^.dmFields := DM_DUPLEX;
  17.        pDev^.dmDuplex := DMDUP_HORIZONTAL;
  18.      DocumentPropertiesW(Handle,PrnH,@NS[1],LPDEVMODEW(pDEV),LPDEVMODEw(pDEV),DM_IN_BUFFER or DM_OUT_BUFFER);
  19.      //If getLastError <> 0 Then it failed!
  20.       end;
  21.     ClosePrinter(PrnH);
  22.     FreeMem(pDev);
  23.    End;
  24. end;                          
  25.  

This gives example of how to Read/Write the DEVMODE of the printer.

P.S.
 Thanks to WP for informing me of the WinUtilPRN unit, it would have saved me some work a few months ago :)

 And of course you must include that along with the Printer unit..

EDIT2:
  I used the wrong DEVMODE, it should be DEVMODEW , sorry...


« Last Edit: June 02, 2018, 03:53:30 am by jamie »
The only true wisdom is knowing you know nothing

RayoGlauco

  • Full Member
  • ***
  • Posts: 174
  • Beers: 1567
Re: Setting printer properties in PrintDialog
« Reply #22 on: June 05, 2018, 01:14:43 pm »
Hello,

I wrote some code to get and set some properties of the printer. I get successfully the current values, but when I call DocumentPropertiesW to change a value, I get no error, but no change is done.

Code: Pascal  [Select][+][-]
  1. // Set new value
  2. if DocumentPropertiesW(0, hPrinter, PWideChar(PrinterNameW), pDM, pDM, DM_IN_BUFFER or DM_OUT_BUFFER) < 0 then
  3.     error_message;
  4. if getLastError <>0 then RaiseLastOSError;
  5. // Check current value
  6. if DocumentPropertiesW(0, hPrinter, PWideChar(PrinterNameW), pDM, nil, DM_OUT_BUFFER) < 0 then
  7.     error_message;

This code runs without error, but no changes are done. I checked it, and pDM has the correct value that I want to set, before and after calling DocumentPropertiesW. But when I call again DocumentPropertiesW to chek if all is ok, I get the original value, not the new one. If I check the printer at the windows control panel, the value is not changed either.

Any idea of what and why is going wrong?
To err is human, but to really mess things up, you need a computer.

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Setting printer properties in PrintDialog
« Reply #23 on: June 05, 2018, 11:16:24 pm »
try the DM_VERTICAL instead..

Also, before calling DocumentProperties after you do a SET, check the DEVMODE record to see it overwrote original
record.
 
  Its possible you may need to split into two records, first read the record, make a copy of it and change the copy, return
the copy for the DM_IN_BUFFER..

 Also there is a possibility your print driver is resetting back to default when close it which can then present a problem here
because the PRINTER class has a handle of its own and it is not the same, usually.
  These go to the print spooler.

I will check later for this.. but please try two different DEVMODE records to make sure things are not getting overlapped.


The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Setting printer properties in PrintDialog
« Reply #24 on: June 06, 2018, 01:25:03 am »
Apparently the DocumentProperties will set the dialog properties and also verifies if the property of the printer
you are attempting to set is a valid one... But it does not actually send it to the driver..

This code here sends it to the driver of the printer....
Code: Pascal  [Select][+][-]
  1. // need to import SetPrinter, it is not in the WinUtilPrn file ?
  2. Function SetPrinter(hPrinter:Handle;Level:DWORD;pPrinter:PByte;Command:DWord):LongBool; StdCall; External
  3.  libWinSpool name 'SetPrinterA';                                        
  4.  
  5. procedure TForm1.Button3Click(Sender: TObject);
  6. Var
  7.    pPrnInFo:pPRINTER_INFO_2;
  8.    pDev:PDevMode;
  9.    H:Handle;
  10.    N:WideString;
  11.    S:Integer;
  12. begin
  13.   N := Printer.PrinterName;
  14.   OpenPrinterW(@N[1],@H, nil);//Open printer;
  15.   GetPrinter(H,2,Nil,0,@S);   //Get Size needed for Info_2;
  16.   GetMem(pPrnInfo,S);
  17.   GetPrinter(H,2,PByte(pPRNInFo),S,@s);
  18.   pDev := pPRNInfo^.pDevMode;
  19.   if pDev^.dmFields and Dm_Orientation <> 0 Then
  20.    Begin
  21.     pDev^.dmOrientation := 2;
  22.    end;
  23.   SetPrinter(H,2,PByte(pPrnInFo),0);  //Need to import the function ? Hmmmmmm
  24.   freeMem(pPrnInfo);
  25.   ClosePrinter(H);
  26. end;                                    
  27.  

 In this example I used the PDF printer to see if I could change the orientation, it succeeded...

 you can change the Duplex mode using the same approach.

 You may want to add some extra error checking on each function return, I did not to shorten it up but it works on my end
for the basic printer. This PC has no printer on  >:(
The only true wisdom is knowing you know nothing

RayoGlauco

  • Full Member
  • ***
  • Posts: 174
  • Beers: 1567
Re: Setting printer properties in PrintDialog
« Reply #25 on: June 06, 2018, 11:03:30 am »
Thank you, jamie,

Finally it seems that all is working. I paste my code, in case someone finds it useful:

Code: Pascal  [Select][+][-]
  1. unit GetAndSetPrinterSettings;   // Only for Windows
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Printers;
  9.  
  10. function SetPrinterOption(prn: tPrinter; FieldToChange: longint; ValueToSet: longint): longint;
  11. function GetPrinterOption(prn: tPrinter; FieldToGet: longint): longint;
  12.  
  13. implementation
  14.  
  15. uses
  16.   Classes, SysUtils, Windows, WinUtilPrn;
  17.  
  18. Function SetPrinter(hPrinter:Handle;Level:DWORD;pPrinter:PByte;Command:DWord):LongBool; StdCall; External
  19.  libWinSpool name 'SetPrinterA';
  20.  
  21. function GetDevModeField(pDM: PDEVMODE; Field: longint): longint;
  22. // Only for fields whose value type and range is integer >=0
  23. // Result >= 0 ==> succeeded
  24. // Result < 0  ==> failed
  25. begin
  26.   if (pDM^.dmFields and Field)=0 then
  27.     Result := -1   // Field not supported
  28.   else
  29.   case Field of
  30.     DM_ORIENTATION: Result := pDM^.dmOrientation;
  31.     DM_PAPERSIZE: Result := pDM^.dmPaperSize;
  32.     DM_PAPERLENGTH: Result := pDM^.dmPaperLength;
  33.     DM_PAPERWIDTH: Result := pDM^.dmPaperWidth;
  34.     DM_SCALE: Result := pDM^.dmScale;
  35.     //  DM_POSITION: Result:=pDM^.dmPosition;
  36.     DM_COPIES: Result := pDM^.dmCopies;
  37.     DM_DEFAULTSOURCE: Result := pDM^.dmDefaultSource;
  38.     DM_PRINTQUALITY: Result := pDM^.dmPrintQuality;
  39.     DM_COLOR: Result := pDM^.dmColor;
  40.     DM_DUPLEX: Result := pDM^.dmDuplex;
  41.     DM_YRESOLUTION: Result := pDM^.dmYResolution;
  42.     DM_TTOPTION: Result := pDM^.dmTTOption;
  43.     DM_COLLATE: Result := pDM^.dmCollate;
  44.     //  DM_FORMNAME: Result:=pDM^.dmFormName;
  45.     DM_LOGPIXELS: Result := pDM^.dmLogPixels;
  46.     DM_ICMMETHOD: Result := pDM^.dmICMMethod;
  47.     DM_ICMINTENT: Result := pDM^.dmICMIntent;
  48.     DM_MEDIATYPE: Result := pDM^.dmMediaType;
  49.     DM_DITHERTYPE: Result := pDM^.dmDitherType;
  50.     else
  51.       Result := -1;   // Field not supported
  52.   end;
  53. end;
  54.  
  55. function SetDevModeField(pDM: PDEVMODE; Field: longint; Value: longint):longint;
  56. // Only for fields whose value type and range is integer >=0
  57.   // Result >= 0 ==> change succeeded; result = previous value (maybe we want to restore it later)
  58.   // Result < 0  ==> change failed
  59. begin
  60.   if (pDM^.dmFields and Field)=0 then
  61.     Result := -1   // Field not supported
  62.   else
  63.   begin
  64.   Result := GetDevModeField(pDM,Field);
  65.   case Field of
  66.     DM_ORIENTATION: pDM^.dmOrientation := Value;
  67.     DM_PAPERSIZE: pDM^.dmPaperSize := Value;
  68.     DM_PAPERLENGTH: pDM^.dmPaperLength := Value;
  69.     DM_PAPERWIDTH: pDM^.dmPaperWidth := Value;
  70.     DM_SCALE: pDM^.dmScale := Value;
  71.     //  DM_POSITION: pDM^.dmPosition := Value;
  72.     DM_COPIES: pDM^.dmCopies := Value;
  73.     DM_DEFAULTSOURCE: pDM^.dmDefaultSource := Value;
  74.     DM_PRINTQUALITY: pDM^.dmPrintQuality := Value;
  75.     DM_COLOR: pDM^.dmColor := Value;
  76.     DM_DUPLEX: pDM^.dmDuplex := Value;
  77.     DM_YRESOLUTION: pDM^.dmYResolution := Value;
  78.     DM_TTOPTION: pDM^.dmTTOption := Value;
  79.     DM_COLLATE: pDM^.dmCollate := Value;
  80.     //  DM_FORMNAME: pDM^.dmFormName := Value;
  81.     DM_LOGPIXELS: pDM^.dmLogPixels := Value;
  82.     DM_ICMMETHOD: pDM^.dmICMMethod := Value;
  83.     DM_ICMINTENT: pDM^.dmICMIntent := Value;
  84.     DM_MEDIATYPE: pDM^.dmMediaType := Value;
  85.     DM_DITHERTYPE: pDM^.dmDitherType := Value;
  86.     else
  87.       Result := -1;   // Field not supported
  88.   end;
  89.   end;
  90. end;
  91.  
  92.  
  93. function SetPrinterOption(prn: tPrinter; FieldToChange: longint; ValueToSet: longint): longint;
  94.   // Only for fields whose value type and range is integer >=0
  95.   // Result > 0 ==> change succeeded; result = previous value (maybe we want to restore it later)
  96.   // Result < 0 ==> change failed
  97.  
  98. label
  99.   exit_with_error;
  100. const
  101.   LEVEL_2 = 2;
  102. var
  103.   hPrinter: tHandle;
  104.   pPrnInFo: pPRINTER_INFO_2;
  105.   pDev:PDevMode;
  106.   datasize: integer;
  107.   PrinterNameW: WideString;
  108. begin
  109.   pPrnInfo:=nil;
  110.   PrinterNameW := prn.PrinterName;
  111.  
  112.   if not OpenPrinterW(PWideChar(PrinterNameW),@hPrinter, nil) then  //Open printer;
  113.     goto exit_with_error;
  114.  
  115.   // Get Size needed for Info_2; GetPrinter returns false but it works ¿?
  116.   GetPrinter(hPrinter, LEVEL_2, Nil, 0, @datasize);
  117.  
  118.   GetMem(pPrnInfo, datasize);
  119.   if pPrnInfo = nil then
  120.     goto exit_with_error;
  121.  
  122.   // get config data; GetPrinter returns false but it works ¿?
  123.   GetPrinter(hPrinter, LEVEL_2 ,PByte(pPRNInFo), datasize ,@datasize);
  124.  
  125.   pDev := pPRNInfo^.pDevMode;
  126.  
  127.   result:= SetDevModeField(pDev, FieldToChange, ValueToSet);
  128.   if result>=0 then
  129.     SetPrinter(hPrinter, LEVEL_2, PByte(pPrnInFo), 0);  // set new config data
  130.  
  131.   // clean and exit
  132.   FreeMem(pPrnInfo);         // Free allocated memory
  133.   ClosePrinter(hPrinter);    // Close printer
  134.   exit;
  135.  
  136.   // ----------------- ERROR ----------------------
  137.   exit_with_error:
  138.     Result := -1;
  139.   if pPrnInfo<>nil then      // Free memory if allocated
  140.     freeMem(pPrnInfo);
  141.   if (hPrinter <> 0) then    // Close printer if opened
  142.     ClosePrinter(hPrinter);
  143. end;
  144.  
  145. function GetPrinterOption(prn: tPrinter; FieldToGet: longint): longint;
  146. // Only for fields whose value type and range is integer >=0
  147. // Result >= 0 ==> succeeded
  148. // Result < 0  ==> failed
  149. label
  150.   exit_with_error;
  151. const
  152.   LEVEL_2 = 2;
  153. var
  154.   hPrinter: tHandle;
  155.   pPrnInFo: pPRINTER_INFO_2;
  156.   pDev:PDevMode;
  157.   datasize: integer;
  158.   PrinterNameW: WideString;
  159. begin
  160.   pPrnInfo:=nil;
  161.   PrinterNameW := prn.PrinterName;
  162.  
  163.   if not OpenPrinterW(PWideChar(PrinterNameW),@hPrinter, nil) then  // Open printer;
  164.     goto exit_with_error;
  165.  
  166.   // Get Size needed for Info_2; GetPrinter returns false but it works ¿?
  167.   GetPrinter(hPrinter, LEVEL_2, Nil, 0, @datasize);
  168.  
  169.   GetMem(pPrnInfo, datasize);
  170.   if pPrnInfo = nil then
  171.     goto exit_with_error;
  172.  
  173.   // get config data; GetPrinter returns false but it works ¿?
  174.   GetPrinter(hPrinter, LEVEL_2 ,PByte(pPRNInFo), datasize ,@datasize);
  175.  
  176.   pDev := pPRNInfo^.pDevMode;
  177.  
  178.   result:= GetDevModeField(pDev, FieldToGet);
  179.  
  180.   // clean and exit
  181.   FreeMem(pPrnInfo);         // Free allocated memory
  182.   ClosePrinter(hPrinter);    // Close printer
  183.   exit;
  184.  
  185.   // ----------------- ERROR ----------------------
  186.   exit_with_error:
  187.     Result := -1;
  188.   if pPrnInfo<>nil then      // Free memory if allocated
  189.     freeMem(pPrnInfo);
  190.   if (hPrinter <> 0) then    // Close printer if opened
  191.     ClosePrinter(hPrinter);
  192. end;
  193.  
  194. end.          

Examples of use:

Code: Pascal  [Select][+][-]
  1.   // uses Printers, Windows, GetAndSetPrinterSettings;
  2.   ActualValue:= GetPrinterOption(Printer, DM_DUPLEX);   // get current value
  3.   // ...
  4.   PreviousValue:= SetPrinterOption(Printer, DM_COLOR, DMCOLOR_MONOCHROME);  // Save value and then change it
  5.   // print something here (output will be monochrome)
  6.   SetPrinterOption(Printer, DM_COLOR, PreviousValue);  // Restore previous value

Edit: some aesthetic changes in the code.
« Last Edit: June 07, 2018, 01:44:37 pm by RayoGlauco »
To err is human, but to really mess things up, you need a computer.

RayoGlauco

  • Full Member
  • ***
  • Posts: 174
  • Beers: 1567
Re: [SOLVED] Setting printer properties in PrintDialog
« Reply #26 on: June 09, 2018, 12:58:01 pm »
I wrote a unit called GetAndSetPrinterSettings, including some more code to access printer settings in Windows.

I attached the unit, in case someone finds it useful. These are the functions it provides:

Code: Pascal  [Select][+][-]
  1. function GetPrinterOption(prn: tPrinter; FieldToGet: longint): longint;
  2. function SetPrinterOption(prn: tPrinter; FieldToChange: longint; ValueToSet: longint): longint;
  3. function GetPrinterSettings(prn: tPrinter; out pDM: PDevMode): boolean;
  4. function SetPrinterSettings(prn: tPrinter; pDM: PDevMode): boolean;
  5. function PrinterSettingsDialog(prn: tPrinter; out pDM: PDevMode; ApplyNow: boolean): boolean;
  6. function PrinterSettingsDialog(prn: tPrinter): boolean;
  7. function GetDevModeField(pDM: PDEVMODE; Field: longint): longint;
  8. function SetDevModeField(pDM: PDEVMODE; Field: longint; Value: longint): longint;

Examples of use:

Code: Pascal  [Select][+][-]
  1. uses
  2.   Printers, Windows, GetAndSetPrinterSettings;
  3. // You must add Printer4Lazarus as a required package
  4. // Not cheching for errors to keep simple the code
  5.  
  6. procedure TForm1.Button1Click(Sender: TObject);
  7. // Example 1: change printer duplex and color/monochrome mode
  8. var
  9.   pDM: PDevMode;
  10. begin
  11.   // get actual settings
  12.   GetPrinterSettings(Printer, pDM);
  13.   // alternate duplex
  14.   if GetDevModeField(pDM, DM_DUPLEX) = DMDUP_SIMPLEX then
  15.     SetDevModeField(pDM, DM_DUPLEX, DMDUP_VERTICAL)
  16.   else
  17.     SetDevModeField(pDM, DM_DUPLEX, DMDUP_SIMPLEX);
  18.   // alternate color/gray
  19.   if GetDevModeField(pDM, DM_COLOR) = DMCOLOR_COLOR then
  20.     SetDevModeField(pDM, DM_COLOR, DMCOLOR_MONOCHROME)
  21.   else
  22.     SetDevModeField(pDM, DM_COLOR, DMCOLOR_COLOR);
  23.   // apply changes to the printer
  24.   SetPrinterSettings(Printer, pDM);
  25.   // free memory
  26.   FreeMem(pDM);
  27. end;
  28.  
  29. procedure TForm1.Button2Click(Sender: TObject);
  30. // Example 2: show a dialog to configure printer
  31. begin
  32.   // ask for and apply new settings
  33.   PrinterSettingsDialog(Printer);
  34. end;
  35.  
  36. procedure TForm1.Button3Click(Sender: TObject);
  37. // Example 3: show a dialog to configure a printing
  38. var
  39.   pOriginalDM: PDevMode;
  40. begin
  41.   // save original settings
  42.   GetPrinterSettings(Printer, pOriginalDM);
  43.   // ask for and apply new settings
  44.   PrinterSettingsDialog(Printer);
  45.   // ... some printing here
  46.   Printer.BeginDoc;
  47.   Printer.Canvas.Font.Size := 14;
  48.   Printer.Canvas.Font.Color := $00ff0044;
  49.   Printer.Canvas.TextOut(200, 200, 'TESTING... ');
  50.   Printer.EndDoc;
  51.   // restore original settings
  52.   SetPrinterSettings(Printer, pOriginalDM);
  53.   // free memory
  54.   FreeMem(pOriginalDM);
  55. end;

I think that printing is a common task in programming, and should be easier in Lazarus. It took me many hours to find the information (only for windows). I still do not understand why Lazarus offers a print dialog with a printer settings button, if when pressing it the user can change many things, but then the programmer can not know what changes made the user.

Edit: some changes in the code & examples; I attached the GetAndSetPrinterSettings unit.
« Last Edit: June 30, 2018, 09:36:44 am by RayoGlauco »
To err is human, but to really mess things up, you need a computer.

dbox

  • Newbie
  • Posts: 1
Re: [SOLVED] Setting printer properties in PrintDialog
« Reply #27 on: July 18, 2018, 08:13:26 pm »
Hi

Functions working great under Windows, but.. How to save &restore printer settings, when printer settings window is "non system", for example from Oki driver? I tried save to registry as binary data pDM variable returned by GetPrinterSettings, but after restore it's not working. Any hint?

I little modified your function GetPrinterSettings:

Code: Pascal  [Select][+][-]
  1. function GetPrinterSettings(prn: tPrinter; out pDM: PDevMode; out dmsize: integer): boolean;

Now i can read and save as binary data ALL printer settings (DevMode+vendor data), dmsize returns properly data size to read from pDM^

@RayoGlauco Thanks for your work
« Last Edit: August 01, 2018, 11:34:13 pm by dbox »

RayoGlauco

  • Full Member
  • ***
  • Posts: 174
  • Beers: 1567
Re: [SOLVED] Setting printer properties in PrintDialog
« Reply #28 on: April 25, 2022, 12:39:37 pm »
Hi, maybe toooo late, but I want to say thanks to dbox. Your contribuition is very useful !
To err is human, but to really mess things up, you need a computer.

 

TinyPortal © 2005-2018