Click to See Complete Forum and Search --> : Problem about Screen Capture


elliottso
December 19th, 2005, 04:28 AM
Hi,

I am trying to implement a screen capture program which will simply output the picture to a window.
I try to modify the following code originally posted here by golanshahar.

RECT rc;
HWND hWnd = ::FindWindow(NULL, "未命名 - 記事本"); // find handle using caption which is only a notepad
::GetWindowRect (hWnd, &rc);
HDC hDC = ::GetDC(0);
HDC memDC = ::CreateCompatibleDC ( hDC );
HBITMAP memBM = ::CreateCompatibleBitmap ( hDC, rc.right-rc.left, rc.bottom-rc.top );
HBITMAP OldBM = (HBITMAP)::SelectObject(memDC, memBM );
::BitBlt( memDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top, hDC, rc.left, rc.top , SRCCOPY );

int size = 3 * ( (rc.right-rc.left) * (rc.bottom-rc.top) );
BYTE *lpBits = new BYTE[size];

::GetBitmapBits( memBM, size, lpBits );

BITMAPINFOHEADER bitmapInfo;
::ZeroMemory(&bitmapInfo,sizeof(BITMAPINFOHEADER));
bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.biWidth = rc.right-rc.left; //enter Width
bitmapInfo.biHeight = rc.bottom-rc.top; //enter Height
bitmapInfo.biPlanes = 1;
bitmapInfo.biBitCount = 24; //bit per pixel 24,32
bitmapInfo.biCompression = 0; //RGB
bitmapInfo.biSizeImage = bitmapInfo.biWidth*bitmapInfo.biHeight*bitmapInfo.biBitCount/8;

HDC hDC2 = ::GetDC((this->GetDlgItem(IDC_PICTURE))->m_hWnd);
::SetDIBitsToDevice(hDC2,
0,0,
rc.right-rc.left,rc.bottom-rc.top,
0,0,
0,rc.bottom-rc.top,
lpBits,
(LPBITMAPINFO)&bitmapInfo,DIB_RGB_COLORS);

delete [] lpBits;
::SelectObject(hDC, OldBM);
::DeleteObject(memBM);
::DeleteObject(memDC);
::ReleaseDC( 0, hDC );

However, when the code is executed, only a bar-code like picture is shown. (the file size is too large to upload)
I would like to ask if there is any problem on the above code?
Thank you.

Marc G
December 19th, 2005, 08:52 AM
You need to call DeleteDC and not DeleteObject to destroy a DC.

The problem is a mismatch between the pixel format of your source and your target.

Instead of using GetBitmapBits, you should use GetDIBits (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_7gms.asp). With this function you can say in which format you want the data. Afterwards, use SetDIBits (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_0qk3.asp) with the correct pixel format.

Also some general info: windows pixels are in BGR(A) and not RGB(A), each row of pixels should be DWORD aligned.

golanshahar
December 19th, 2005, 02:57 PM
did you step in debgger?
are you sure that this able to find the window?

HWND hWnd = ::FindWindow(NULL, "未命名 - 記事本");

and that hWnd is not null? cause it looks pretty strange to me. :confused:

one more thing this code above assume you work with 24 bit image in case you are using 32 bit you need to change couple of things:

instead of

int size = 3 * ( (rc.right-rc.left) * (rc.bottom-rc.top) );


you need to put

int size = 4 * ( (rc.right-rc.left) * (rc.bottom-rc.top) );


and instead of:

bitmapInfo.biBitCount = 24;
you should put:

bitmapInfo.biBitCount = 32;

Cheers