2
votes

I'm trying to write a copy of what my apps window looks like periodically. Things work fine if the window is normalized I.e. on the desk top. But if the window is minimized, I get only the minimized command bar.

I've tried various approaches using SendMessage with WM_PRINT and PrintWindow without success. In the following code using SendMessage, I know that the proper size of the normalized window is used to create the bitmap. I know that the default processing for WM_PRINT via DefWindowProc generated a WM_PRINTCLIENT message. hWnd is the handle for the minimized window.

        HDC                 scrdc, memdc;
        HBITMAP             membit;
        WINDOWPLACEMENT     WP;
        EncoderParameters   encoderParameters;
        ULONG               quality;
        Status              status;
        RECT                Rect;

        WP.length  = sizeof (WP);
        WP.flags   = 0;
        WP.showCmd = 0;

        GetWindowPlacement (hWnd, &WP);
        int WPHeight = WP.rcNormalPosition.bottom - WP.rcNormalPosition.top;
        int WPWidth  = WP.rcNormalPosition.right  - WP.rcNormalPosition.left;

        scrdc = GetWindowDC (hWnd);                                 // source DC
        GetWindowRect(hWnd,&Rect);                                  //  source Rectangle
        int Height = Rect.bottom-Rect.top;                          //   source height
        int Width  = Rect.right-Rect.left;                          //    source width

        if (WP.showCmd == SW_SHOWMINIMIZED)
        {
            Height = WPHeight;
            Width  = WPWidth;
        }

        memdc = CreateCompatibleDC(scrdc);                          // destination DC
        membit = CreateCompatibleBitmap(scrdc, Width, Height);      //  destination bitmap
        HBITMAP hOldBitmap =(HBITMAP) SelectObject(memdc, membit);  //   add bitmap to DC

// copy screen to new BitMap

//      BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);   

//      PrintWindow (hWnd, memdc, 0);

        BitBlt 
        (
            memdc,
            0,
            0,
            GetDeviceCaps(memdc,HORZRES),
            GetDeviceCaps(memdc,VERTRES),
            NULL,
            NULL,
            NULL,
            WHITENESS
        );

        SendMessage (hWnd, WM_PRINT, unsigned int (memdc), PRF_CLIENT|PRF_NONCLIENT);

And here is the code for the WM_PRINT, WM_PRINTCLIENT, and WM_PAINT handlers

    case WM_PRINT:
        return DefWindowProc (hWnd, message, wParam, lParam);

    case WM_PRINTCLIENT:
        Screen.WMPrint (hWnd, HDC (wParam), NULL);
        return true;
        return DefWindowProc (hWnd, message, wParam, lParam);

    case WM_PAINT:                          
        Screen.WMPaint (hWnd);
        break;

I also know that Screen.WMPrint scribbles the proper stuff in the HDC.

So if anyone can give me some hints or suggest an approach, I'd greatly appreciate it. I could use Screen.WMPaint but then I get only the client area and miss the command bar and the borders.

I do not want to normalize the window since that would annoy the user.

3
Would hiding the window, restoring it, using PrintWindow, minimizing it, and finally showing it work? There might be something you can do about the activity in the taskbar with that too.chris

3 Answers

0
votes

This is hard because, when your window is minimized, it doesn't really look like its un-minimized self.

WM_PRINT prints the non-client area of your window (since you're passing the flag), by calling the usual WM_NCPAINT handler. And that handler looks at the window state, so if it's minimized, you won't get what you want. And then it tries to print the client area, but (I suspect) here too the minimized state causes this part to be skipped--a minimized window effective has no client area.

Calling your internal paint routine may be the simplest solution. Yes, it will give you only the client area. Notice that the previews you see on the Windows 7 task bar when you hover over the tile for a minimized window also exclude the non-client area. I think it's too hard.

0
votes

In your WM_PAINT handler, assuming you're using double buffering, make your backbuffer hdc global, and then when you want to take a snapshot of your program, just bitblt that HDC to an off-screen bitmap and there you have it.

Here's what your WM_PAINT handler should look like: http://pastebin.com/aNvtHiD6

0
votes

This it might be just possible to construct such a bit map. I think one would have to glom onto a bitmap of the entire window after each paint operation in order to get the title bar and borders. Then one could erase the client area. This would give a starting point in which one could do various GDI operations. An added complication is that any controls such as scroll bars, date controls, edit boxes, etc. would have to be individually captured and added to the bitmap. For my application, I decided I would not handle the minimized situation. I had enough trouble getting the controls onto the new bitmap. The problem with the controls arises because one cannot simply make them children of the main window because all you have is a bitmap, the window itself being minimized or the controls obscured or off the screen.