2011-07-31 4 views
3

Windows XP에서 프로그램을 인쇄 할 수 있어야하므로 XPS API를 사용할 수 없습니다.WinSpool API를 사용하여 용지 크기를 설정하는 방법은 무엇입니까?

WinSpool을 사용하여 레터에서 A4로 용지 크기를 설정하려고합니다. 내가 액세스 권한과 관련된 두 가지 문제가

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 호출이 성공하고 정보 구조는 양호하지만 SetPrinter에 대한 호출이 실패합니다.

충분히 흥미롭게도 SetPrinter의 결과를 무시하면 SetPrinter이 실패하더라도 인쇄 대화 상자에 A4가 프린터 크기로보고됩니다.

내가 잘못했는데 OpenPrinter에 올바르게 PDeviceMode를 설치하면 충분합니까? (I 실제로 VCL에 대한

:-) 또 다른 질문을이 질문을 작성 후이 함께했다 :

나는 버퍼가 그 매개 변수로 전달 얻을 할 필요가 얼마나 큰 알고 어떻게 Printers 장치를 사용하는 경우 TPrinter.GetPrinter 방법으로?

배경 :

시스템은 : 영어 로케일 윈도우 7 프로페셔널 64 비트 영어.

네트워크 프린터 (Brother HL-5350DN)에서 A4 용지로 인쇄하려고합니다.

제어판의 모든 프린터 설정을 A4 용지로 설정했지만 작성중인 Delphi 2009 프로그램은 여전히 ​​US Letter의 용지 크기를 가져옵니다.

즉, : 델파이 프로그램은 프린터 스풀러의 기본 설정을 따르지 않습니다.

먼저 TPrinterDialog를 실행하고 수동으로 (고급 프린터 설정에서) 올바른 용지 크기를 선택하면 모든 것이 정상입니다.

프로그램이 UI없이 실행되어야하므로 프로그래밍 방식으로 또는이 프로그램을 기본 Windows 프린터 스풀러 설정을 고려하여 바람직하게 해결해야합니다.

어쩌면 나는 중요한 설정을 놓쳤을까요?

+0

작동이 남자를 시도? –

+0

@David : TPrinter에는 PageFormat 설정이 없습니다. 볼 수있는 유일한 방법은 TPrinter.GetPrinter 및 TPrinter.SetPrinter를 사용하는 것입니다. 'TPrinter.GetPrinter'의 인수에 할당 할 공간이 얼마나되는지 어떻게 알 수 있습니까? –

+0

실제로 여기서 무엇을하려고합니까? 분명히 프린터는 용지의 크기를 알고 있습니다. 사용자는 프린터 환경 설정 대화 상자에서 원하는 용지함을 선택합니다. 코드에서 용지 크기를 변경할 수 없습니다! 문제의 한 작은 모서리에 창문을 제공하는 대신 전체 이야기를 들려 주시면 도움이 될 것입니다. –

답변

1

데이빗 (David)이 썼듯이 Windows에서 올바른 프린터 기본 설정을 지정하면 문제가 해결됩니다.

내 응용 프로그램의 로컬 인쇄 속성을 설정하는 방법을 찾지 못했지만 더 이상 필요하지 않습니다.

Sertac이 쓴 것처럼 TPrinter.GetPrinterTPrinter.SetPrinter을 사용하여 글로벌 프린터 기본 설정을 읽고 쓸 수 있습니다.(질문에 대한 의견보기)

아무도 anwser를 제공하지 않았고 문제가 해결되었으므로 커뮤니티 위키로 표시하고 있습니다. 이 대답을 자유롭게 개선하십시오.

7

는 그것은 나를 왜 TPrinter를 사용할 수 없습니다

uses WinSpool,Windows,System; 

procedure SetPrinterInfo(APrinterName: PChar); 
var 

    HPrinter : THandle; 
    InfoSize, 
    BytesNeeded: Cardinal; 
    DevMode : PDeviceMode; 
    PI2: PPrinterInfo2; 
    PrinterDefaults: TPrinterDefaults; 

begin 
    with PrinterDefaults do 
    begin 
    DesiredAccess := PRINTER_ACCESS_USE; 
    pDatatype := nil; 
    pDevMode := nil; 
    end; 
    if OpenPrinter(APrinterName, HPrinter, @PrinterDefaults) then 
    try 
    SetLastError(0); 
    //Determine the number of bytes to allocate for the PRINTER_INFO_2 construct... 
    if not GetPrinter(HPrinter, 2, nil, 0, @BytesNeeded) then 
    begin 
     //Allocate memory space for the PRINTER_INFO_2 pointer (PrinterInfo2)... 
     PI2 := AllocMem(BytesNeeded); 
     try 
     InfoSize := SizeOf(TPrinterInfo2); 
     if GetPrinter(HPrinter, 2, PI2, BytesNeeded, @BytesNeeded) then 
     begin 
      DevMode := PI2.pDevMode; 
      DevMode.dmFields := DevMode.dmFields or DM_PAPERSIZE; 
      DevMode.dmPaperSize := DMPAPER_A4; 
      PI2.pSecurityDescriptor := nil; 
      // Apply settings to the printer 
      if DocumentProperties(0, hPrinter, APrinterName, PI2.pDevMode^, 
           PI2.pDevMode^, DM_IN_BUFFER or DM_OUT_BUFFER) = IDOK then 
      begin 
      SetPrinter(HPrinter, 2, PI2, 0); // Ignore the result of this call... 
      end; 
     end; 
     finally 
     FreeMem(PI2, BytesNeeded); 
     end; 
    end; 
    finally 
    ClosePrinter(HPrinter); 
    end; 
end; 
관련 문제