Windows printer driver
Asked Answered
B

2

-4

we currently have bought a program for calculation etc, but which us don't allow duplex print. But our real Printer does support it.

I wanted to ask if it is possible to set a "printer driver" between the application and the real printer, which i can send the document too. In this driver i say that it should print in duplex.

im currently programming only with C# and .NET and i had never been further with c++ or c

can you give me some hints to get started with that?

Brakesman answered 12/7, 2017 at 7:37 Comment(5)
Why don't you use the PrintDocument class? It has a Duplex property...Groggery
yeah i was thinking about that, just print it from the program to a specific folder and then just check that folder with a self written program to just print it, when some file is in their, but i want to know if their is a way for the user without a extra program, e.g. without printing it as pdf,Brakesman
I don't know how the calculation program looks like. Is it just a c# library you can use?Groggery
no, i have no access to the code from the programBrakesman
If you setup your "default printer settings" (in your printer) to print as "duplex" - is not printing in duplex ? If the application just prints, then the "default printer settings" may be sufficient. (Control Panel -> Devices and Printers -> <your printer> -> Printer -> Printing PreferencesCuirassier
B
5

The duplex class is from a microsoft documentation,forgot the actual link Attached for you to use,

using System.Runtime.InteropServices;
using System;


namespace STACK.OVERFLOW
{
    public class Duplexprint
    {

        #region Win32 API Declaration


        [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern Int32 GetLastError();


        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool ClosePrinter(IntPtr hPrinter);


        [DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPStr)]
            string pDeviceNameg, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);


        [DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, ref Int32 dwNeeded);


        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault);


        [DllImport("winspool.Drv", EntryPoint = "SetPrinterA", ExactSpelling = true, SetLastError = true)]
        public static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinter, int Command);


        [StructLayout(LayoutKind.Sequential)]
        public struct PRINTER_DEFAULTS
        {
            public IntPtr pDatatype;
            public IntPtr pDevMode;
            public int DesiredAccess;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PRINTER_INFO_9
        {

            public IntPtr pDevMode;
            // Pointer to SECURITY_DESCRIPTOR
            public int pSecurityDescriptor;
        }

        public const short CCDEVICENAME = 32;

        public const short CCFORMNAME = 32;

        [StructLayout(LayoutKind.Sequential)]
        public struct DEVMODE
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
            public string dmDeviceName;
            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;
            public short dmOrientation;
            public short dmPaperSize;
            public short dmPaperLength;
            public short dmPaperWidth;
            public short dmScale;
            public short dmCopies;
            public short dmDefaultSource;
            public short dmPrintQuality;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]
            public string dmFormName;
            public short dmUnusedPadding;
            public short dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
        }


        public const Int64 DM_DUPLEX = 0x1000L;
        public const Int64 DM_ORIENTATION = 0x1L;
        public const Int64 DM_SCALE = 0x10L;
        public const Int64 DMORIENT_PORTRAIT = 0x1L;
        public const Int64 DMORIENT_LANDSCAPE = 0x2L;
        public const Int32 DM_MODIFY = 8;
        public const Int32 DM_COPY = 2;
        public const Int32 DM_IN_BUFFER = 8;
        public const Int32 DM_OUT_BUFFER = 2;
        public const Int32 PRINTER_ACCESS_ADMINISTER = 0x4;
        public const Int32 PRINTER_ACCESS_USE = 0x8;
        public const Int32 STANDARD_RIGHTS_REQUIRED = 0xf0000;
        public const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
        //added this 
        public const int CCHDEVICENAME = 32;
        //added this 
        public const int CCHFORMNAME = 32;

        #endregion

        #region Public Methods


        /// <summary>
        /// Method Name : GetPrinterDuplex 
        /// Programmatically get the Duplex flag for the specified printer 
        /// driver's default properties. 
        /// </summary>
        /// <param name="sPrinterName"> The name of the printer to be used. </param>
        /// <param name="errorMessage"> this will contain error messsage if any. </param>
        /// <returns> 
        /// nDuplexSetting - One of the following standard settings: 
        /// 0 = Error
        /// 1 = None (Simplex)
        /// 2 = Duplex on long edge (book) 
        /// 3 = Duplex on short edge (legal) 
        /// </returns>
        /// <remarks>
        /// </remarks>
        public short GetPrinterDuplex(string sPrinterName, out string errorMessage)
        {
            errorMessage = string.Empty;
            short functionReturnValue = 0;
            IntPtr hPrinter = default(IntPtr);
            PRINTER_DEFAULTS pd = default(PRINTER_DEFAULTS);
            DEVMODE dm = new DEVMODE();
            int nRet = 0;
            pd.DesiredAccess = PRINTER_ACCESS_USE;
            nRet = OpenPrinter(sPrinterName, out hPrinter, ref pd);
            if ((nRet == 0) | (hPrinter.ToInt32() == 0))
            {
                if (GetLastError() == 5)
                {
                    errorMessage = "Access denied -- See the article for more info.";
                }
                else
                {
                    errorMessage = "Cannot open the printer specified " + "(make sure the printer name is correct).";
                }
                return functionReturnValue;
            }
            nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, IntPtr.Zero, 0);
            if ((nRet < 0))
            {
                errorMessage = "Cannot get the size of the DEVMODE structure.";
                goto cleanup;
            }
            IntPtr iparg = Marshal.AllocCoTaskMem(nRet + 100);
            nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, iparg, IntPtr.Zero, DM_OUT_BUFFER);
            if ((nRet < 0))
            {
                errorMessage = "Cannot get the DEVMODE structure.";
                goto cleanup;
            }
            dm = (DEVMODE)Marshal.PtrToStructure(iparg, dm.GetType());
            if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX))
            {
                errorMessage = "You cannot modify the duplex flag for this printer " + "because it does not support duplex or the driver " + "does not support setting it from the Windows API.";
                goto cleanup;
            }
            functionReturnValue = dm.dmDuplex;

            cleanup:
            if ((hPrinter.ToInt32() != 0))
                ClosePrinter(hPrinter);
            return functionReturnValue;
        }


        /// <summary>
        /// Method Name : SetPrinterDuplex     
        /// Programmatically set the Duplex flag for the specified printer driver's default properties. 
        /// </summary>
        /// <param name="sPrinterName"> sPrinterName - The name of the printer to be used. </param>
        /// <param name="nDuplexSetting"> 
        /// nDuplexSetting - One of the following standard settings: 
        /// 1 = None 
        /// 2 = Duplex on long edge (book) 
        /// 3 = Duplex on short edge (legal) 
        /// </param>
        ///  <param name="errorMessage"> this will contain error messsage if any. </param>
        /// <returns>
        /// Returns: True on success, False on error.
        /// </returns>
        /// <remarks>
        /// 
        /// </remarks>
        public bool SetPrinterDuplex(string sPrinterName, int nDuplexSetting, out string errorMessage)
        {
            errorMessage = string.Empty;
            bool functionReturnValue = false;
            IntPtr hPrinter = default(IntPtr);
            PRINTER_DEFAULTS pd = default(PRINTER_DEFAULTS);
            PRINTER_INFO_9 pinfo = new PRINTER_INFO_9();
            DEVMODE dm = new DEVMODE();
            IntPtr ptrPrinterInfo = default(IntPtr);
            int nBytesNeeded = 0;
            int nRet = 0;
            Int32 nJunk = default(Int32);
            if ((nDuplexSetting < 1) | (nDuplexSetting > 3))
            {
                errorMessage = "Error: dwDuplexSetting is incorrect.";
                return functionReturnValue;
            }
            pd.DesiredAccess = PRINTER_ACCESS_USE;
            nRet = OpenPrinter(sPrinterName, out hPrinter, ref pd);
            if ((nRet == 0) | (hPrinter.ToInt32() == 0))
            {
                if (GetLastError() == 5)
                {
                    errorMessage = "Access denied -- See the article for more info.";
                }
                else
                {
                    errorMessage = "Cannot open the printer specified " + "(make sure the printer name is correct).";
                }
                return functionReturnValue;
            }
            nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, IntPtr.Zero, 0);
            if ((nRet < 0))
            {
                errorMessage = "Cannot get the size of the DEVMODE structure.";
                goto cleanup;
            }
            IntPtr iparg = Marshal.AllocCoTaskMem(nRet + 100);
            nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, iparg, IntPtr.Zero, DM_OUT_BUFFER);
            if ((nRet < 0))
            {
                errorMessage = "Cannot get the DEVMODE structure.";
                goto cleanup;
            }
            dm = (DEVMODE)Marshal.PtrToStructure(iparg, dm.GetType());
            if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX))
            {
                errorMessage = "You cannot modify the duplex flag for this printer " + "because it does not support duplex or the driver " + "does not support setting it from the Windows API.";
                goto cleanup;
            }
            dm.dmDuplex = (short)nDuplexSetting;
            Marshal.StructureToPtr(dm, iparg, true);
            nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, pinfo.pDevMode, pinfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
            if ((nRet < 0))
            {
                errorMessage = "Unable to set duplex setting to this printer.";
                goto cleanup;
            }
            GetPrinter(hPrinter, 9, IntPtr.Zero, 0, ref nBytesNeeded);
            if ((nBytesNeeded == 0))
            {
                errorMessage = "GetPrinter failed.";
                goto cleanup;
            }
            ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded + 100);
            nRet = GetPrinter(hPrinter, 9, ptrPrinterInfo, nBytesNeeded, ref nJunk) ? 1 : 0;
            if ((nRet == 0))
            {
                errorMessage = "Unable to get shared printer settings.";
                goto cleanup;
            }
            pinfo = (PRINTER_INFO_9)Marshal.PtrToStructure(ptrPrinterInfo, pinfo.GetType());
            pinfo.pDevMode = iparg;
            pinfo.pSecurityDescriptor = 0;
            Marshal.StructureToPtr(pinfo, ptrPrinterInfo, true);
            nRet = SetPrinter(hPrinter, 9, ptrPrinterInfo, 0) ? 1 : 0;
            if ((nRet == 0))
            {
                errorMessage = "Unable to set shared printer settings.";
            }
            functionReturnValue = Convert.ToBoolean(nRet);
            cleanup:
            if ((hPrinter.ToInt32() != 0))
                ClosePrinter(hPrinter);
            return functionReturnValue;
        }
        #endregion
    }
}

Example on the usage of the function

private string GetDefaultPrinter()
{
    PrinterSettings settings = new PrinterSettings();
    foreach (string printer in PrinterSettings.InstalledPrinters)
    {
        settings.PrinterName = printer;
        if (settings.IsDefaultPrinter)
            return printer;
    }
    return string.Empty;
}

public void printthis()
{
    Duplexprint ds = new Duplexprint();
    string printername = GetDefaultPrinter();
    string errorMessage = string.Empty;
    ds.SetPrinterDuplex(printername, 2, out errorMessage);

    object Co = "1";
    object Pa = "1";
    object oT = true;
    object oF = false;

    if (Apptype == Applicationtypes.Word)
    {
        oDoc.PrintOut(ref oT, ref oF, ref obj, ref obj, ref obj,
        ref obj, ref obj, ref Co, ref Pa, ref obj, ref oF, ref oT,
        ref obj, ref obj, ref obj, ref obj, ref obj, ref obj);
    }
    else
    {
        xlWorkSheet.PrintOut(Type.Missing, Type.Missing, Type.Missing, Type.Missing,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing);
    }

    ds.SetPrinterDuplex(printername, 1, out errorMessage);
}
Boorman answered 17/7, 2017 at 7:15 Comment(1)
thanks for you answer, (since nobody like the question, without telling why?...) well i don't have the time at this moment, to focus on this. When i have any further question on this, i will be back on this.Brakesman
L
0

We also had to switch to a Post Script driver to get the above code to work in our newer 2021 printer, a Konica Minolta bizhub 808 (958).

Lucubration answered 25/7, 2023 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.