Jacob Quisenberry
Jacob Quisenberry

Reputation: 1199

Reading a Printer Device Context in C#

I am able to display and save a screen device to DIB bitmap, and I would like to do the same with a printer device context. I can get a non-null bitmap, but it is always solid black.

Here is the code that allows me to handle a screen device context.

        //In size variable we shall keep the size of the window.
        SIZE size;

        //Win32 API functions are imported in classes
        //PlatformInvokeGDI32
        //PlatformInvokeUSER32

        //Get handle of calc.exe window.
        IntPtr hwnd = PlatformInvokeUSER32.FindWindow("SciCalc", "Calculator");

        //Get window dimensions
        PlatformInvokeUSER32.RECT rect;
        PlatformInvokeUSER32.GetWindowRect(hwnd, out rect);
        size.cx = rect._Right - rect._Left;
        size.cy = rect._Bottom - rect._Top;

        //Get the device context of Calculator.
        IntPtr hDC = PlatformInvokeUSER32.GetDC(hwnd);

        //Draw on the Calculator surface.
        Graphics CalculatorGraphics = Graphics.FromHdc(hDC);
        Color colorRed = Color.FromName("Red");
        Pen penRed = new Pen(colorRed);
        CalculatorGraphics.DrawEllipse(penRed, 50, 50, 50, 50);
        CalculatorGraphics.Save();

        //Here we make a compatible device context in memory for screen device context.
        IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC);

        //Create a compatible bitmap of window size and using screen device context.
        m_HBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(hDC, size.cx, size.cy);

        //As m_HBitmap is IntPtr we can not check it against null. For this purspose IntPtr.Zero is used.
        if (m_HBitmap != IntPtr.Zero)
        {
            //Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap.
            IntPtr hOld = (IntPtr)PlatformInvokeGDI32.SelectObject(hMemDC, m_HBitmap);
            //We copy the Bitmap to the memory device context.
            PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, PlatformInvokeGDI32.SRCCOPY);
            //We select the old bitmap back to the memory device context.
            PlatformInvokeGDI32.SelectObject(hMemDC, hOld);
            //We delete the memory device context.
            PlatformInvokeGDI32.DeleteDC(hMemDC);
            //We release the screen device context.
            PlatformInvokeUSER32.ReleaseDC(hwnd, hDC);
            //Image is created by Image bitmap handle and returned.
            return System.Drawing.Image.FromHbitmap(m_HBitmap);
        }
        //If m_HBitmap is null retunrn null.
        return null;

Here is how I get a printer device context:

        //In size variable we shall keep the size of the window.
        SIZE size;
        size.cx = 1000;
        size.cy = 1000;

        //Get Printer Handle
        IntPtr PrinterHandle;
        PlatformInvokeGDI32.PRINTER_DEFAULTSW defaults = new PlatformInvokeGDI32.PRINTER_DEFAULTSW();
        PlatformInvokeGDI32.OpenPrinterW("Bullzip PDF Printer", out PrinterHandle, defaults);

        //Get Printer Device context
        IntPtr PrinterHDC = PlatformInvokeGDI32.CreateDCW("", "Bullzip PDF Printer", "", IntPtr.Zero);

        //Initialize DocInfo structure.
        PlatformInvokeGDI32.DOCINFOW docInfo = new PlatformInvokeGDI32.DOCINFOW();

        //Start printing.
        PlatformInvokeGDI32.StartDocW(PrinterHDC, ref docInfo);
        PlatformInvokeGDI32.StartPage(PrinterHDC);
        Graphics graphics = Graphics.FromHdc(PrinterHDC, PrinterHandle);

        Color theColor = Color.FromName("Red");
        Pen pen = new Pen(theColor);
        graphics.DrawRectangle(pen, 50, 50, 50, 50);
        graphics.DrawEllipse(pen, 50, 50, 50, 50);
        graphics.Save();

        //Here we make a compatible device context in memory for screen device context.
        IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(PrinterHDC);

        //Create a compatible bitmap of window size and using screen device context.
        m_HBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(PrinterHDC, size.cx, size.cy);

        //As m_HBitmap is IntPtr we can not check it against null. For this purspose IntPtr.Zero is used.
        if (m_HBitmap != IntPtr.Zero)
        {
            //Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap.
            IntPtr hOld = (IntPtr)PlatformInvokeGDI32.SelectObject(hMemDC, m_HBitmap);
            //We copy the Bitmap to the memory device context.
            PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0, size.cx, size.cy, PrinterHDC, 0, 0, PlatformInvokeGDI32.SRCCOPY);
            //We select the old bitmap back to the memory device context.
            PlatformInvokeGDI32.SelectObject(hMemDC, hOld);
            //We delete the memory device context.
            PlatformInvokeGDI32.DeleteDC(hMemDC);
            //We release the screen device context.
            //PlatformInvokeUSER32.ReleaseDC(hwnd, PrinterHDC);
            //Image is created by Image bitmap handle and returned.

            PlatformInvokeGDI32.EndPage(PrinterHDC);
            PlatformInvokeGDI32.EndDoc(PrinterHDC);
            PlatformInvokeGDI32.ClosePrinter(PrinterHandle);
            pen.Dispose();
            graphics.Dispose();


            return System.Drawing.Image.FromHbitmap(m_HBitmap);
        }
        //If m_HBitmap is null retunrn null.
        return null;

How can I draw on the printer device context? How can I save the printer device context to DIB?

Thank you,

Jacob

Upvotes: 2

Views: 3386

Answers (1)

arx
arx

Reputation: 16896

Printer device contexts are write-only.

For example, suppose you are printing to a PostScript printer. You create a printer device context and draw some text on it. The printer device driver does not render a bitmap containing your text. Rather, it creates a sequence of PostScript commands to draw the text and sends the commands to the printer. In other words, there is no bitmap to be copied.

What are you trying to achieve?

Upvotes: 2

Related Questions