2012-06-21 2 views
0

여러 페이지로 된 문서를 인쇄하는 프로그램이 있습니다. 첫 번째 페이지는 미리 인쇄 된 용지이므로 첫 번째면에 인쇄해야하고 나머지 페이지는 양면 인쇄해야합니다.인쇄 작업 중간에 양면 인쇄를 변경하는 방법

초기 솔루션은 첫 번째 페이지 다음에 빈 용지를 인쇄하는 것이었지만 많은 프린터 (또는 모든 프린터)는 미리 인쇄 된 용지의 앞면과 다른면을 사용했습니다 (매우 나쁜). 양면 인쇄를 위해 설정됩니다.

인쇄 작업 도중 프린터가 양면 인쇄를 변경하도록 설득하려고했습니다. 나는 행운없이 이걸 가지고 싸워 왔고, 다양한 코드 샘플을 사용하면 이론적으로는 효과가 있지만 그렇지 않습니다.

양면 인쇄를 변경해야 할 경우 각 EndPage를 호출 한 후 프린터에서 장치 컨텍스트를 가져오고 (내부 클래스의 비공개 필드 인 yuck을 사용) 마샬 러를 사용하여 DEVMODE 구조체의 값을 채 웁니다 , 장치 컨텍스트 및 DEVMODE 포인터를 사용하여 ResetDC()를 호출합니다.

포인터를 확인하기 위해서만 DEVMODE 구조를 검색합니다. 정확한 필드를 설정하고 싶습니다. DEVMODE는 올바르게 채워지고 ResetDC() 및 PrinterSettings.SetHdevmode()로 보내지지만 PrinterSettings.GetHdevmode()를 다시 검색하면 방금 변경 한 내용이 사라집니다. 그리고 프린터는 이전 양면 인쇄 설정을 유지합니다.

편집 : OnStartPage가 ResetDC를 호출한다는 것과 같은 전에 내가 게시 한 코드에 몇 가지 문제점이 있습니다. 그래서 StandardPrintController가 보유한 DEVMODE 구조체를 수정해야합니다. 그러나이 변경 사항으로는 여전히 작동하지 않습니다.

public class PrinterDuplexController : StandardPrintController 
{ 
    public PrinterDuplexController() 
    { 
    } 

    private static FieldInfo dcField = typeof(StandardPrintController) 
     .GetField("dc", 
     BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); 
    private static FieldInfo modeHandleField = typeof(StandardPrintController) 
     .GetField("modeHandle", 
     BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); 

    protected object dc 
    { 
     get 
     { 
      return dcField.GetValue(this); 
     } 
    } 

    protected IntPtr Hdc 
    { 
     get 
     { 
      var dc = this.dc; 
      return (IntPtr)(dc.GetType().GetProperty("Hdc").GetValue(dc, null)); 
     } 
    } 
    protected IntPtr modeHandle 
    { 
     get 
     { 
      object result = modeHandleField.GetValue(this); 
      var field = result.GetType().GetField("handle", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic); 
      return (IntPtr)field.GetValue(result); 
     } 
    } 

    public override void OnEndPage(PrintDocument document, PrintPageEventArgs e) 
    { 
     base.OnEndPage(document, e); 
     IntPtr pDEVMODE = GlobalLock(modeHandle); 
     try 
     { 
      int[] flags = new int[1]; 
      Marshal.Copy(
       new IntPtr(40 + pDEVMODE.ToInt64()), 
       flags, 
       0, 
       1); 
      flags[0] |= (int)DM.Duplex; 
      Marshal.Copy(
       flags, 
       0, 
       new IntPtr(40 + pDEVMODE.ToInt64()), 
       1); 



      Marshal.Copy(
       new short[] { (short)e.PageSettings.PrinterSettings.Duplex }, 
       0, 
       new IntPtr(62 + pDEVMODE.ToInt64()), 
       1); 

      var debugDevMode = (DEVMODE)Marshal.PtrToStructure(pDEVMODE, typeof(DEVMODE)); 

      ResetDC(Hdc, pDEVMODE); 
     } 
     finally 
     { 
      GlobalUnlock(modeHandle); 
     } 
    } 

    [DllImport("gdi32.dll")] 
    //private static extern IntPtr ResetDC(IntPtr hdc, [In] ref DEVMODE lpInitData); 
    private static extern int ResetDC(IntPtr hdc, IntPtr DevMode); 

    [DllImport("gdi32.dll")] 
    public static extern int StartPage(IntPtr hdc); 

    [DllImport("gdi32.dll")] 
    public static extern int EndPage(IntPtr hdc); 

    [DllImport("kernel32.dll", ExactSpelling = true)] 
    private static extern IntPtr GlobalFree(IntPtr handle); 

    [DllImport("kernel32.dll", ExactSpelling = true)] 
    private static extern IntPtr GlobalLock(IntPtr handle); 

    [DllImport("kernel32.dll", ExactSpelling = true)] 
    private static extern IntPtr GlobalUnlock(IntPtr handle); 

    [Flags()] 
    internal enum DM : int 
    { 
     Orientation = 0x1, 
     PaperSize = 0x2, 
     PaperLength = 0x4, 
     PaperWidth = 0x8, 
     Scale = 0x10, 
     Position = 0x20, 
     NUP = 0x40, 
     DisplayOrientation = 0x80, 
     Copies = 0x100, 
     DefaultSource = 0x200, 
     PrintQuality = 0x400, 
     Color = 0x800, 
     Duplex = 0x1000, 
     YResolution = 0x2000, 
     TTOption = 0x4000, 
     Collate = 0x8000, 
     FormName = 0x10000, 
     LogPixels = 0x20000, 
     BitsPerPixel = 0x40000, 
     PelsWidth = 0x80000, 
     PelsHeight = 0x100000, 
     DisplayFlags = 0x200000, 
     DisplayFrequency = 0x400000, 
     ICMMethod = 0x800000, 
     ICMIntent = 0x1000000, 
     MediaType = 0x2000000, 
     DitherType = 0x4000000, 
     PanningWidth = 0x8000000, 
     PanningHeight = 0x10000000, 
     DisplayFixedOutput = 0x20000000 
    } 

    internal struct POINTL 
    { 
     public int x; 
     public int y; 
    } 


    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] 
    internal struct DEVMODE 
    { 
     public const int CCHDEVICENAME = 32; 
     public const int CCHFORMNAME = 32; 

     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)] 
     [FieldOffset(0)] 
     public string dmDeviceName; 
     [FieldOffset(32)] 
     public Int16 dmSpecVersion; 
     [FieldOffset(34)] 
     public Int16 dmDriverVersion; 
     [FieldOffset(36)] 
     public Int16 dmSize; 
     [FieldOffset(38)] 
     public Int16 dmDriverExtra; 
     [FieldOffset(40)] 
     public DM dmFields; 

     [FieldOffset(44)] 
     Int16 dmOrientation; 
     [FieldOffset(46)] 
     Int16 dmPaperSize; 
     [FieldOffset(48)] 
     Int16 dmPaperLength; 
     [FieldOffset(50)] 
     Int16 dmPaperWidth; 
     [FieldOffset(52)] 
     Int16 dmScale; 
     [FieldOffset(54)] 
     Int16 dmCopies; 
     [FieldOffset(56)] 
     Int16 dmDefaultSource; 
     [FieldOffset(58)] 
     Int16 dmPrintQuality; 

     [FieldOffset(44)] 
     public POINTL dmPosition; 
     [FieldOffset(52)] 
     public Int32 dmDisplayOrientation; 
     [FieldOffset(56)] 
     public Int32 dmDisplayFixedOutput; 

     [FieldOffset(60)] 
     public short dmColor; 
     [FieldOffset(62)] 
     public short dmDuplex; 
     [FieldOffset(64)] 
     public short dmYResolution; 
     [FieldOffset(66)] 
     public short dmTTOption; 
     [FieldOffset(68)] 
     public short dmCollate; 
     [FieldOffset(72)] 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)] 
     public string dmFormName; 
     [FieldOffset(102)] 
     public Int16 dmLogPixels; 
     [FieldOffset(104)] 
     public Int32 dmBitsPerPel; 
     [FieldOffset(108)] 
     public Int32 dmPelsWidth; 
     [FieldOffset(112)] 
     public Int32 dmPelsHeight; 
     [FieldOffset(116)] 
     public Int32 dmDisplayFlags; 
     [FieldOffset(116)] 
     public Int32 dmNup; 
     [FieldOffset(120)] 
     public Int32 dmDisplayFrequency; 
    } 
} 

답변

1

두 가지 인쇄 작업을 각각 다른 양면 인쇄 설정으로 사용해보십시오. 내부 분야를 해킹하는 대신 작업 순서를 정하기 위해 우선 순위를 부여하는 바이올린.

+1

저는 이것이 매우 최후의 수단이 될 것이라고 생각합니다. 이것들은 실제로 하나의 인쇄 작업이며 그것을 분할하려고 시도하는 것은 완전히 구축되고 처리되는 방식을 완전히 바꾸는 것을 의미합니다. 또한, 나는 그것을 수행하는 델파이 코드를 가지고 있으므로 Windows에서 처리 할 수 ​​있지만 질문은 .NET에서 처리하는 방법입니다. –

+2

StandardPrintController에서 내려와 base.OnEndPrint()/base.OnStartPrint()를 호출하여 PrintDocument의 중간에서 새 인쇄 작업을 시작할 수 있으므로 여러 개의 PrintDocuments를 만들지 않아도되었습니다. 그것은 내가해야하는 것을 두려워했던 것이다). –

관련 문제