0

複数ページのドキュメントを印刷するプログラムがあります。最初のページは事前に印刷された用紙であるため、最初の面に印刷し、残りのページは両面印刷する必要があります。

私の最初の解決策は、最初のページの後に白紙を印刷することでしたが、多くの(またはすべての)プリンターは、設定されているかどうかに応じて、事前に印刷された用紙の異なる面を前面として使用します(非常に悪い)二重化するかどうか。

そのため、印刷ジョブの途中で両面印刷を変更するようにプリンタを説得しようとして立ち往生しています。私は運がなくてこれと戦ってきました。さまざまなコードサンプルを使用すると、理論的には機能するはずですが、機能しません。

各EndPage呼び出しの後、二重化を変更する必要がある場合は、プリンターからデバイスコンテキストを取得し(内部クラスのプライベートフィールドでのリフレクションを使用して、yuck)、Marshalを使用して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;
    }
}
4

1 に答える 1

1

それぞれ異なる両面設定で 2 つの印刷ジョブを作成してみてください。内部フィールドをハックするのではなく、ジョブの優先順位をいじって順番に並べます。

于 2012-06-21T16:14:48.043 に答える