Thread: grab contents of non visible window

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    11

    grab contents of non visible window

    Hi,

    I'd like to screengrab a window even when it is not visible but can't work out how to do it and I wonder if someone can help me.

    The function below grabs the contents of the window ok if I set it as the foreground window first with a very short delay of a couple of hundred ms to ensure it has been drawn, but this feels very much like a fudge.

    Thanks

    Code:
    void CaptureWindow ( HWND hwnd )
    {
        RECT            rect;
    	HDC				src_hdc;
    	HDC				dst_hdc;
    	HBITMAP			hbitmap;
    	BITMAPINFO		bi;
    	LPBYTE			pBits;
    	int				w;
    	int				h;
    	HANDLE			file_handle;
    
    	GetClientRect ( hwnd, &rect );
    
    	w = rect.right - rect.left;
    	h = rect.bottom - rect.top;
    
    	src_hdc = GetDC ( hwnd );
    
    	dst_hdc = CreateCompatibleDC ( src_hdc );
    
    	ZeroMemory ( &bi, sizeof ( bi ) );
    	bi.bmiHeader.biSize = sizeof ( bi.bmiHeader );
    	bi.bmiHeader.biHeight = h;
    	bi.bmiHeader.biWidth = w;
    	bi.bmiHeader.biPlanes = 1;
    	bi.bmiHeader.biBitCount = 24;
    	bi.bmiHeader.biCompression = BI_RGB;
    	bi.bmiHeader.biSizeImage = ((w * bi.bmiHeader.biBitCount +31)& ~31) / 8 * h; 
    
    	hbitmap = CreateDIBSection ( src_hdc, &bi, DIB_RGB_COLORS, (LPVOID *) &pBits, NULL, 0 );
    
    	SelectObject ( dst_hdc, hbitmap );		
    
    	if ( BitBlt ( dst_hdc, 0, 0, w, h, src_hdc, rect.left, rect.top, SRCCOPY ) ) {
    
    	  	file_handle = CreateFile ( "grab.bmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );	
    
    		if ( file_handle != INVALID_HANDLE_VALUE ) {
    			DWORD				dwRet = 0;
    			BITMAPFILEHEADER	bfh;
    
    			ZeroMemory ( &bfh, sizeof ( bfh ) );
    			bfh.bfType = 0x4D42;
    			bfh.bfOffBits = sizeof ( BITMAPFILEHEADER ) + sizeof ( BITMAPINFOHEADER );
    			bfh.bfSize = bi.bmiHeader.biSizeImage + bfh.bfOffBits;
    
    	 		WriteFile ( file_handle, &bfh, sizeof ( bfh ), &dwRet, NULL);
    			WriteFile ( file_handle, &bi.bmiHeader, sizeof ( bi.bmiHeader ), &dwRet, NULL );
    			WriteFile ( file_handle, pBits, bi.bmiHeader.biSizeImage, &dwRet, NULL );
    		}
    
    		CloseHandle ( file_handle );
    		DeleteDC ( dst_hdc );
    		DeleteObject ( hbitmap );
       		ReleaseDC ( hwnd, src_hdc );
    	}
    }

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    >>to screengrab a window even when it is not visible<<

    When a window is visible, the system renders it to its device context, or the bitmap selected into it. Accordingly, when it's not visible the device context bitmap is likely to be empty or contain only information relevant to its current state (minimized, hidden, etc.). This is why your function works only when the target window is in the foreground: that's the only state when the system must fully render the window.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    11
    Thanks Ken,

    So does that mean it is impossible to grab the contents of a non-visible window ?

    If so, is there a way for me to detect when the window has completed drawing instead of putting in a forced delay after setting it as the foreground window ?

  4. #4
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Not necessarily. I'd imagine that a window with its own dc (CS_OWNDC registered window class style) might retain bitmap data but I'm not sure. I don't think it's a common style but you could always use GetClassInfoEx to find out if the target window has that class style prior to attempting the bitmap capture.

    I'm not sure if there's an easy way to detect if it's finished drawing but you might be able to force it to update by sending an InvalidateRect/UpdateWindow to it prior to commencing your image capture code.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  5. #5

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    11
    I've tried the .dll injection method on that site but without luck - a .bmp is being copied to the clipboard but it is always just a black screen. The site mentions it being for NT, so do you know if it should actually work on XP as well?

    ps I'm using Vistual Studio 7.0 whereas the project file is for 7.1 so there is a possibility that I've converted it incorrectly.

    Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. WM_CAPTION causing CreateWindowEx() to fail.
    By Necrofear in forum Windows Programming
    Replies: 8
    Last Post: 04-06-2007, 08:23 AM
  2. 6 measly errors
    By beene in forum Game Programming
    Replies: 11
    Last Post: 11-14-2006, 11:06 AM
  3. OpenGL Window
    By Morgul in forum Game Programming
    Replies: 1
    Last Post: 05-15-2005, 12:34 PM
  4. problem with open gl engine.
    By gell10 in forum Game Programming
    Replies: 1
    Last Post: 08-21-2003, 04:10 AM
  5. opengl code not working
    By Unregistered in forum Windows Programming
    Replies: 4
    Last Post: 02-14-2002, 10:01 PM