From:  smcl@speed.kiev.ua (Scott McLoughlin)
Subject: Re: window dump in windows [LONG] [CODE]
Reply-To: smcl@speed.kiev.ua
Organization: Private Scott McLoughlin
Date: Thu, 28 Jan 93 03:23:05 +0200

Howdy,

> Can someone tell me what I'm doing wrong here? I'm trying to print the
> image/bitmap of my main window.

Yea, I've done this. Probably not a good idea. (see below)

> Here is my (undoubtably stupid) method...

Nah, that's what I (and probably _every_ other windows programmer)
tried at first.

>    /* mainDC is obtained with GetDC()    */
>    /* printDC is obtained via PrintDlg() */
>    /* error checking deleted for clarity */
>    Escape(printDC, STARTDOC, 6, "My App", NULL);
>    BitBlt(printDC, 0, 0, 1000, 1000, mainDC, 0, 0, SRCCOPY);
>    Escape(printDC, NEWFRAME, 0, NULL, NULL);
>    Escape(printDC, ENDDOC, 0, NULL, NULL);

> When my code executes, all I get is a page ejected from the printer (which
> is a Canon BJ10E). What am I leaving out in my quick and dirty method?

Welcome to windows.

The printer DC and the display (window) DC are not compatible.
If I remember correctly, you have to retrieve the bitmap from the window,
select this bitmap into a memory DC then bitblt to the printer DC.

I wrote just such a function for a co. I worked for about a year ago or
so.  I happen to have the function lying around.  The code is below.
I _think_ that this is the final version that works.  If not, sorry.

::NOTE::  Once I wrote the routine, the functionality was inadequate.
Once again, if memory serves, while DIBs come out nice and gray scaled
on a HP, the aforementioned method produced lame black and white
output (yellows and greens didn't show), and the fonts scaled (or rather,
do not scale) poorly.

I moved on to other tasks.  Another bloke wrote a very nice routine
to have all the graphics output to a metafile (one with the funny
scalable header) which could be played either to the screen or to
the printer.  If that sounds tougher, you're right.  No query
GDI functions played to the metafile, no MM_TEXT mode, careful to use
LOGFONTS, etc. ** In the end though, the output was impressive. **

Read Petzold on GDI very carefully.  Then learn all about reading/writing/
/scaling/displaying DIBs and their palettes (most of this is folklore
here on the net, CI$ and BIX/WIX).  Oh yeah, read _Advanced Windows
Programming_ by Martin Heller.  Good discussions of bitmapped graphics
display using GDI.

All this makes one realize that
even though GDI is nicer than, say, Borland's BGI (_not_ a crit, I've
done and seen some nifty stuff done with BGI), it is still pretty low level.
For clean, maintainable application design, you probably want to add
another "virtual" output layer in there that suits your application.

> Thanks,
Your welcome.
> john
Scott McLoughlin

----------  CODE LISTING FOLLOWS

/**************************************************************************
**
**      FILE:
**
**              BITPRN.CPP
**
**      PURPOSE:
**
**              Print a bitmap to a printer.
**
**************************************************************************/

#include <windows.h>
#include <iostream.h>
#include "bitprn.h"



BOOL prnWin(HWND hWnd, HDC hdcPrn, BOOL doMax) {

        POINT   ptPrintSize;
        RECT    rectWinSize;
        HDC     hdcWin, hdcMem;
        HBITMAP hbmOld, hbmTest;

        int     iDevCaps = GetDeviceCaps(hdcPrn, RASTERCAPS);
        char    szJobName[] = "TestBitBlt";

        /* Maximize the window if requested.
        */
        if (doMax) {
                SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0L);
        }

        /* Get Printer Page dimensions and
        ** Window Dimensions
        */
        Escape(hdcPrn, GETPHYSPAGESIZE, NULL, NULL, (char far*) &ptPrintSize);
        GetClientRect(hWnd, &rectWinSize);

// NOTE: If I remember correctly, these tests return inaccurate
//      negative results for _many_ drivers, including HP
//      drivers.  But that was Win 3.0. Anyway...

        /* Test for BitBlt/StretchBlt capabilities
        ** If printer cannot print bitmaps, then
        ** return FALSE.
        */
        if ((iDevCaps & RC_BITBLT) != RC_BITBLT) {
                MessageBox(hWnd, "Printer is not able to\nprint bitmaps.",
                        "Error!", MB_OK | MB_ICONEXCLAMATION);
                return (FALSE);
        } else if ((iDevCaps & RC_STRETCHBLT) != RC_STRETCHBLT) {
                MessageBox(hWnd, "Printer is not able to\nstretch bitmaps.",
                        "Warning!", MB_OK | MB_ICONEXCLAMATION);
                // No need to return
        }


        /* Create memory DC and bitmap.
        ** Clean up during error handling!
        */
        if ((hdcWin = GetDC(hWnd)) == 0)
                return (FALSE);
        if ((hdcMem = CreateCompatibleDC(hdcWin)) == 0) {
                ReleaseDC(hWnd, hdcWin); // Clean up
                return (FALSE);
        }
        if ((hbmTest = CreateCompatibleBitmap(
          hdcWin, rectWinSize.right, rectWinSize.bottom)) == 0) {
                ReleaseDC(hWnd, hdcWin); // Clean up
                DeleteDC(hdcMem);
                return (FALSE);
        }

        /* Copy screen image into bitmap
        */
        hbmOld = SelectObject(hdcMem, hbmTest);
        BitBlt(hdcMem, 0, 0, rectWinSize.right, rectWinSize.bottom,
                hdcWin, 0, 0, SRCCOPY);


        /* Start Document.  If failure, clean up.
        */
        if (Escape(hdcPrn, STARTDOC, sizeof(szJobName), szJobName,NULL) < 1) {
                MessageBox(hWnd, "Problem starting document.", "Error!",
                        MB_OK | MB_ICONEXCLAMATION);

                SelectObject(hdcMem, hbmOld); // Clean up
                DeleteDC(hdcMem);
                DeleteObject(hbmTest);
                ReleaseDC(hWnd, hdcWin);
                return (FALSE);
        }

        /* Copy bitmap to printer
        */
        if (BitBlt(hdcPrn,
                0, 0, rectWinSize.right, rectWinSize.bottom,
                hdcMem, 0, 0, SRCCOPY) == 0) {
                MessageBox(hWnd, "Unsuccessful BitBlt!", "Error!",
                        MB_OK | MB_ICONEXCLAMATION);
        }

        /* New page and end document
        */
        if (Escape(hdcPrn, NEWFRAME, 0, NULL, NULL) > 0)
                Escape(hdcPrn, ENDDOC, 0, NULL, NULL);

        /* Clean up
        */
        SelectObject(hdcMem, hbmOld);
        DeleteObject(hbmTest);
        DeleteDC(hdcMem);
        ReleaseDC(hWnd, hdcWin);
        return (TRUE);
}




Newsgroups: comp.os.ms-windows.programmer.misc