Author: William Gerbert
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, 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:
Solve 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:
1 uses
2 printers, registry;
3
4 {$R *.dfm}
5
6 procedure SaveCurrentPrinterSettings(reg: TRegistry);
7 var
8 Device, Driver, Port: array[0..80] of Char;
9 DevMode: THandle;
10 pDevmode: PDeviceMode;
11 begin
12 Printer.GetPrinter(Device, Driver, Port, DevMode);
13 if Devmode <> 0 then
14 begin
15 {lock it to get pointer to DEVMODE record}
16 pDevMode := GlobalLock(Devmode);
17 if pDevmode <> nil then
18 try
19 reg.WriteBinaryData(device, pDevmode^, sizeof(TDevicemode));
20 finally
21 {unlock devmode handle.}
22 GlobalUnlock(Devmode);
23 end;
24 end;
25 end;
26
27 procedure LoadCurrentPrinterSettings(reg: TRegistry);
28 var
29 Device, Driver, Port: array[0..80] of Char;
30 DevMode: THandle;
31 pDevmode: PDeviceMode;
32 begin
33 Printer.GetPrinter(Device, Driver, Port, DevMode);
34 if Devmode <> 0 then
35 begin
36 {lock it to get pointer to DEVMODE record}
37 pDevMode := GlobalLock(Devmode);
38 if pDevmode <> nil then
39 try
40 reg.ReadBinaryData(device, pDevmode^, sizeof(TDevicemode));
41 finally
42 {unlock devmode handle.}
43 GlobalUnlock(Devmode);
44 end;
45 end;
46 end;
47
48 procedure TForm1.Button1Click(Sender: TObject);
49 var
50 reg: TRegistry;
51 begin
52 reg := TRegistry.Create(KEY_READ or KEY_WRITE);
53 try
54 reg.RootKey := HKEY_CURRENT_USER;
55 if reg.OpenKey('Software\PB\Test', true) then
56 try
57 SaveCurrentPrinterSettings(reg);
58 finally
59 reg.CloseKey;
60 end
61 finally
62 reg.free
63 end;
64 end;
65
66 procedure TForm1.Button2Click(Sender: TObject);
67 var
68 reg: TRegistry;
69 begin
70 reg := TRegistry.Create(KEY_READ);
71 try
72 reg.RootKey := HKEY_CURRENT_USER;
73 if reg.OpenKey('Software\PB\Test', false) then
74 try
75 LoadCurrentPrinterSettings(reg);
76 finally
77 reg.CloseKey;
78 end
79 finally
80 reg.free
81 end;
82 end;
83
84 procedure TForm1.Button3Click(Sender: TObject);
85 begin
86 printdialog1.execute
87 end;
Solve 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.
88 function GetPrinterName: string;
89 var
90 prnIndex: Integer;
91 prnList: TStrings;
92 begin
93 result := '';
94 prnIndex := Printers.Printer.PrinterIndex;
95 prnList := Printers.Printer.Printers;
96 if (prnIndex > -1) and (prnIndex < prnList.Count) then
97 begin
98 if (prnList.Objects[prnIndex] <> nil) then
99 result := TPrinterDevice(prnList.Objects[prnIndex]).Device
100 else
101 result := prnList[prnIndex];
102 end;
103 end;
104
105 procedure ShowPrinterInfo;
106 const
107 LEVEL_2 = 2;
108 var
109 printerHandle: THandle;
110 printerInfo: TPrinterInfo2;
111 bytesNeeded: Cardinal;
112 printerDefaults: TPrinterDefaults;
113 prnName: string;
114 pBuffer: Pointer;
115 gpResult: Boolean;
116 devInfo: TDevMode;
117 sMsg: string;
118 begin
119 printerHandle := 0;
120 ClearRecord(printerInfo, SizeOf(TPrinterInfo2));
121 ClearRecord(printerDefaults, SizeOf(TPrinterDefaults));
122 prnName := GetPrinterName;
123 if not OpenPrinter(PChar(prnName), printerHandle, @printerDefaults) then
124 Exit;
125 try
126 gpResult := WinSpool.GetPrinter(printerHandle, LEVEL_2, @printerInfo,
127 SizeOf(printerInfo), @bytesNeeded);
128 if not gpResult and (bytesNeeded > SizeOf(PrinterInfo)) then
129 {get printer call failed because buffer passed was too small}
130 begin
131 GetMem(pBuffer, bytesNeeded); {allocate buffer of needed size}
132 try
133 {protect buffer memory allocate}
134 gpResult := WinSpool.GetPrinter(PrinterHandle, LEVEL_2, pBuffer,
135 bytesNeeded, @bytesNeeded);
136 {call GetPrinter() again with new, bigger buffer}
137 if gpResult then
138 {success second time}
139 printerInfo := PPrinterInfo2(pBuffer)^;
140 {1st bytes are info record, copy values}
141 finally
142 FreeMem(pBuffer); {deallocate buffer}
143 end;
144 end;
145 if gpResult then
146 begin
147 sMsg := '';
148 devInfo := printerInfo.pDevMode^;
149 if ((DM_PAPERSIZE and devInfo.dmFields) > 0) then
150 sMsg := 'Paper Size: ' + PaperSizeToStr(devInfo.dmPaperSize) + #13;
151 if ((DM_PAPERLENGTH and devInfo.dmFields) > 0) then
152 sMsg := sMsg + 'Paper Length: ' + IntToStr(devInfo.dmPaperLength) + #13;
153 if ((DM_PAPERWIDTH and devInfo.dmFields) > 0) then
154 sMsg := sMsg + 'Paper Width: ' + IntToStr(devInfo.dmPaperWidth) + #13;
155 ShowMessage(sMsg);
156 end;
157 finally
158 ClosePrinter(printerHandle);
159 end;
160 end;
|