How to save and load printer settings to / from the registry #104
Question
I'm trying to get Windows to remember settings - in particular paper
type, size and orientation - configured using the Printer Setup
dialogue. It's confusing me. It seems that sometimes Windows remembers
these settings and sometimes not. The technique I'm considering is to
read and save (to an INI file or wherever) the
Printer.PageHeight, Printer.PageWidth etc. values
for the particular printer concerned, so they're available to be loaded
for subsequent sessions. What better solutions would people suggest? I
can't find a way to get the name of the currently selected paper layout
(e.g. Letter, Legal, etc.). It's not among the properties of TPrinter.
Anyone have a way to get / set this? I'm working with D5 pro (D6 soon),
developing in Win2K, deploying to various flavours from Win'9X to XP.
Answer 1
Windows remembers only changes made to the default settings, using the printer icon in the control panels printers applet. A solution for you would be to save the printers devicemode record, the public part at least:
uses printers, registry; {$R *.dfm} procedure SaveCurrentPrinterSettings(reg: TRegistry); var Device, Driver, Port: array[0..80] of Char; DevMode: THandle; pDevmode: PDeviceMode; begin Printer.GetPrinter(Device, Driver, Port, DevMode); if Devmode <> 0 then begin {lock it to get pointer to DEVMODE record} pDevMode := GlobalLock(Devmode); if pDevmode <> Nil then try reg.WriteBinaryData(device, pDevmode^, sizeof(TDevicemode)); finally {unlock devmode handle.} GlobalUnlock(Devmode); end; end; end; procedure LoadCurrentPrinterSettings(reg: TRegistry); var Device, Driver, Port: array[0..80] of Char; DevMode: THandle; pDevmode: PDeviceMode; begin Printer.GetPrinter(Device, Driver, Port, DevMode); if Devmode <> 0 then begin {lock it to get pointer to DEVMODE record} pDevMode := GlobalLock(Devmode); If pDevmode <> Nil then try reg.ReadBinaryData(device, pDevmode^, sizeof(TDevicemode)); finally {unlock devmode handle.} GlobalUnlock(Devmode); end; end; end; procedure TForm1.Button1Click(Sender: TObject); var reg: TRegistry; begin reg:= TRegistry.Create(KEY_READ OR KEY_WRITE); try reg.RootKey := HKEY_CURRENT_USER; if reg.OpenKey('Software\PB\Test', true) then try SaveCurrentPrinterSettings(reg); finally reg.CloseKey; end finally reg.free end; end; procedure TForm1.Button2Click(Sender: TObject); var reg: TRegistry; begin reg:= TRegistry.Create(KEY_READ); try reg.RootKey := HKEY_CURRENT_USER; if reg.OpenKey('Software\PB\Test', false) then try LoadCurrentPrinterSettings(reg); finally reg.CloseKey; end finally reg.free end; end; procedure TForm1.Button3Click(Sender: TObject); begin printdialog1.execute end;
Tip by Peter Below
Answer 2
Check out the Delphi Win API help for GetPrinter, PRINTER_INFO_2, and DEVMODE. I use the following code to read the current info for the printer.
I'm attempting to find some code to set the values, but I'm having problems with user rights in Win2000 Pro. Use the Delphi select printer dialog to set the current printer, otherwise the code will display the settings of the default printer if one is set.
function GetPrinterName: String; var prnIndex: Integer; prnList: TStrings; begin result := ''; prnIndex := Printers.Printer.PrinterIndex; prnList := Printers.Printer.Printers; if (prnIndex > - 1) and (prnIndex < prnList.Count) then begin if (prnList.Objects[prnIndex] <> nil) then result := TPrinterDevice(prnList.Objects[prnIndex]).Device else result := prnList[prnIndex]; end; end; procedure ShowPrinterInfo; const LEVEL_2 = 2; var printerHandle: THandle; printerInfo: TPrinterInfo2; bytesNeeded: Cardinal; printerDefaults: TPrinterDefaults; prnName: String; pBuffer: Pointer; gpResult: Boolean; devInfo: TDevMode; sMsg: String; begin printerHandle := 0; ClearRecord(printerInfo, SizeOf(TPrinterInfo2)); ClearRecord(printerDefaults, SizeOf(TPrinterDefaults)); prnName := GetPrinterName; if not OpenPrinter( PChar(prnName), printerHandle, @printerDefaults ) then Exit; try gpResult := WinSpool.GetPrinter( printerHandle, LEVEL_2, @printerInfo, SizeOf(printerInfo), @bytesNeeded ); if not gpResult and (bytesNeeded > SizeOf(PrinterInfo)) then begin {get printer call failed because buffer passed was too small} GetMem(pBuffer, bytesNeeded); {allocate buffer of needed size} try {protect buffer memory allocate} {call GetPrinter() again with new, bigger buffer} gpResult := WinSpool.GetPrinter( PrinterHandle, LEVEL_2, pBuffer, bytesNeeded, @bytesNeeded ); if gpResult then {success second time} {1st bytes are info record, copy values} printerInfo := PPrinterInfo2(pBuffer)^; finally FreeMem(pBuffer); {deallocate buffer} end; end; if gpResult then begin sMsg := ''; devInfo := printerInfo.pDevMode^; if ((DM_PAPERSIZE and devInfo.dmFields) > 0) then sMsg := 'Paper Size: ' + PaperSizeToStr(devInfo.dmPaperSize) + #13; if ((DM_PAPERLENGTH and devInfo.dmFields) > 0) then sMsg := sMsg + 'Paper Length: ' + IntToStr(devInfo.dmPaperLength) + #13; if ((DM_PAPERWIDTH and devInfo.dmFields) > 0) then sMsg := sMsg + 'Paper Width: ' + IntToStr(devInfo.dmPaperWidth) + #13; ShowMessage(sMsg); end; finally ClosePrinter(printerHandle); end; end;
Tip by David Beardwood
Original resource: | The Delphi Pool |
---|---|
Author: | Peter Below & David Beardwood |
Added: | 2009/09/14 |
Last updated: | 2009/09/14 |