News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

About PrintWindow

Started by Tam, July 27, 2008, 01:35:53 PM

Previous topic - Next topic

Tam

#define _WIN32_WINNT    0x0501        //xp
#include <windows.h>

int main()
{
    RECT rc;
    HWND hwnd = FindWindow(TEXT("Notepad"), NULL);    //the window can't be min
    if (hwnd == NULL)
    {
        cout << "it can't find any 'note' window" << endl;
        return 0;
    }
    GetClientRect(hwnd, &rc);

    //create
    HDC hdcScreen = GetDC(NULL);
    HDC hdc = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen,
        rc.right - rc.left, rc.bottom - rc.top);
    SelectObject(hdc, hbmp);

    //Print to memory hdc
    PrintWindow(hwnd, hdc, PW_CLIENTONLY);

    //copy to clipboard
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hbmp);
    CloseClipboard();
   
    //release
    DeleteDC(hdc);
    DeleteObject(hbmp);
    ReleaseDC(NULL, hdcScreen);

    cout << "success copy to clipboard, please paste it to the 'mspaint'" << endl;
   
    return 0;
}

result:


what's the wrong in my code? why the window 'offset' to right-bottom?

thanks

Tam

by the way,
PrintWindow(hwnd, hdc, 0);
will work well, but it's not only Print 'Client', it will print all rectangle of the window.

Tam

any one can help me?

is this the API bug of microsoft Windows XP?

jj2007

What do you mean with PrintWindow(hwnd, hdc, 0) works well? What do you see if you use PW_CLIENTONLY?

jj2007

You are right, the behaviour is not as expected. I post the code translated to Masm in case somebody is willing to solve the mystery. hOwn stands for the window to be printed

LOCAL hdcScreen, hCdc, hbmp, hOwn
LOCAL rc:RECT
mov hOwn, whateverwindowyouwanttoprint ; fails for a richedit - all black
invoke GetDC, NULL ; HDC hdcScreen = GetDC(NULL);
mov hdcScreen, eax
invoke CreateCompatibleDC, eax ;hdc = CreateCompatibleDC(hdcScreen);
mov hCdc, eax
invoke GetClientRect, hOwn, addr rc
mov eax, rc.right
sub eax, rc.left
mov ecx, rc.bottom
sub ecx, rc.top

; HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, rc.right - rc.left, rc.bottom - rc.top);
invoke CreateCompatibleBitmap, hdcScreen, eax, ecx
mov hbmp, eax
invoke SelectObject, hCdc, hbmp ; SelectObject(hdc, hbmp);
push eax
invoke PrintWindow, hOwn, hCdc, PW_CLIENTONLY    ; PrintWindow(hwnd, hdc, PW_CLIENTONLY);
pop eax
invoke SelectObject, hCdc, eax ; free bitmap

; copy to clipboard
invoke OpenClipboard, NULL
invoke EmptyClipboard
invoke SetClipboardData, CF_BITMAP, hbmp
invoke CloseClipboard

; release
invoke DeleteDC, hCdc
invoke DeleteObject, hbmp
invoke ReleaseDC, NULL, hdcScreen

jj2007

It's worthwhile playing with the WM_PRINT message, as it is more flexible.

invoke SelectObject, hCdc, hbmp ; SelectObject(hdc, hbmp);
push eax
if 1    ; conditional assembly - both codes do roughly the same
invoke SendMessage, hOwn, WM_PRINT, hCdc,
PRF_ERASEBKGND or PRF_CLIENT or PRF_CHILDREN
else
invoke PrintWindow, hOwn, hCdc, PW_CLIENTONLY    ; PrintWindow(hwnd, hdc, PW_CLIENTONLY);
endif
pop eax
invoke SelectObject, hCdc, eax ; free bitmap

Tedd

Not that this is a C++ forum :P


GetClientRect returns the top-left coordinates as (0,0).

So then you copy the rectangle (0,0,width,height) from the screen DC, and that's what you get - the top left corner of the screen.

Use ClientToScreen to convert (rc.left,rc.top) to the correct screen coordinates.
Also, since the top-left is given as (0,0) there's no need to calculate the width and height, they are simply rc.right and rc.bottom.



[Attachment: example in both C++ and asm]

[attachment deleted by admin]
No snowflake in an avalanche feels responsible.

jj2007

>    invoke BitBlt, imgDC,0,0,[r.right],[r.bottom],scrDC,[r.left],[r.top],SRCCOPY

Tedd, you are cheating - this is a PrintWindow thread  :wink
But you are perfectly right about GetClientRect. To print the whole window, GetWindowRect does the job. However, if you don't use PRF_NONCLIENT, the result looks pretty odd.

invoke GetWindowRect, hPW, addr rc
mov eax, rc.right
sub eax, rc.left
mov ecx, rc.bottom
sub ecx, rc.top

; HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, rc.right - rc.left, rc.bottom - rc.top);
invoke CreateCompatibleBitmap, hdcScreen, eax, ecx
mov hbmp, eax
invoke SelectObject, hCdc, hbmp ; SelectObject(hdc, hbmp);
push eax
invoke SendMessage, hPW, WM_PRINT, hCdc,
PRF_ERASEBKGND or PRF_CHILDREN or PRF_OWNED or PRF_CLIENT or PRF_NONCLIENT