Поскольку никто не предоставил ответ, и проблема теперь решена, я отмечаю это как вики сообщества. Не стесняйтесь, чтобы улучшить этот ответ.
могу использовать API XPS, так как программа должна быть в состоянии печатать на Windows XP.
Я пытаюсь установить размер бумаги от Letter до A4, используя WinSpool.
Это мой тестовый код:
var
H : THandle;
I : TBytes;
Info : PPrinterInfo2;
NeededSize : DWORD;
DevMode : PDeviceMode;
PD : TPrinterDefaults;
begin
PD.pDatatype := nil;
PD.pDevMode := nil;
PD.DesiredAccess := PRINTER_ACCESS_ADMINISTER;
if not OpenPrinter('Brother HL-5350DN series Printer', H, @PD) then begin
raise Exception.Create('OpenPrinter error: ' + SysErrorMessage(GetLastError));
end;
try
Assert(not GetPrinter(H, 2, nil, 0, @NeededSize));
SetLength(I, NeededSize);
Info := @I[0];
if not GetPrinter(H, 2, Info, NeededSize, @NeededSize) then begin
raise Exception.Create('GetPrinter error: ' + SysErrorMessage(GetLastError));
end;
DevMode := Info.pDevMode;
DevMode.dmFields := DevMode.dmFields or DM_PAPERSIZE;
DevMode.dmPaperSize := DMPAPER_A4;
Info.pSecurityDescriptor := nil; // According to MSDN it has to be niled if we're not going to change it.
if not SetPrinter(H, 2, Info, 0) then begin
raise Exception.Create('SetPrinter error: ' + SysErrorMessage(GetLastError));
end;
finally
ClosePrinter(H);
end;
TPrintDialog.Create(Self).Execute; // This is just so I can check the paper size
end;
У меня есть две проблемы, связанные с правами доступа.
Если я установлюPD.DesiredAccess
вPRINTER_ACCESS_ADMINISTER
GetPrinter
вызов не удается, я думаю, это связано с UAC.
Если я установлю его наPRINTER_ACCESS_USE
GetPrinter
вызов успешен и структура Info в порядке, но вызовSetPrinter
выходит из строя.
Достаточно интересно, когда я игнорирую РезультатSetPrinter
в диалоговом окне печати отображается размер принтера A4, хотяSetPrinter
выходит из строя.
Я делаю это совершенно неправильно, и достаточно передать правильно настроенный PDeviceMode в OpenPrinter? (Я действительно придумал это после написания этого вопроса :-)
Еще один вопрос относительно VCL:
Если я используюPrinters
блок, как я знаю, насколько большими должны быть буферы, которые передаются в качестве параметров вTPrinter.GetPrinter
метод?
Фон:
Система: Windows 7 Профессиональная 64-битная английская с английским языком.
Я пытаюсь распечатать на бумаге формата A4 на сетевом принтере (Brother HL-5350DN).
Я установил все настройки принтера на панели управления на бумагу A4, но программа Delphi 2009, которую я пишу, все еще получает размеры бумаги для US Letter.
Другими словами: программа Delphi не соответствует настройкам по умолчанию диспетчера очереди печати.
Если я сначала запускаю TPrinterDialog и вручную выбираю правильный размер бумаги (в дополнительных настройках принтера), все в порядке.
Программа должна работать без какого-либо пользовательского интерфейса, поэтому я должен решить эту проблему программно, или желательно, чтобы программа просто учитывала настройки диспетчера очереди печати Windows по умолчанию.
Может быть, я пропустил какое-то неосведомленное урегулирование?