问题
We are trying to develop a solution where a Desktop screen from a Windows XP machine needs to be monitored remotely.
From our experience, we have identified that GDI based approach is faster than that of DirectX front buffer capture.
In GDI we are getting the handle to the screen as follows.
// Get the Desktop windows handle and device context
hDesktopWnd=GetDesktopWindow();
hDesktopDC=GetDC(hDesktopWnd);
// Get the handle to the existing DC and create a bitmap file object
HDC hBmpFileDC=CreateCompatibleDC(hDesktopDC);
HBITMAP hBmpFileBitmap=CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);
// Assign the object in Memory DC to the bitmap and perform a bitblt
SelectObject(hBmpFileDC,hBmpFileBitmap);
BitBlt(hBmpFileDC,0,0,nWidth,nHeight,hDesktopDC,0,0,SRCCOPY|CAPTUREBLT);
// Assign the bitmap handle to a CImage Object
CImage m_temp;
m_temp.Attach(hBmpFileBitmap);
m_temp.Save("d:\\Images\\Image10.bmp");
This operation saves the m_temp CImage object on the hard drive at the given path which means that this object actually holds the data from the screen. But in my application, I want to process the images in the desktop buffer for which I need to have the image data buffer pointer. But when I call function m_temp.GetBits() which is suppsoed to return the pointer of the data , I get NULL pointer there. (I can see the m_temp holding the correct height, width, bits/pixel data valiues but the image data buffer pointer is NULL)
Even the functions like
BITMAP bitmap;
GetObject(hBmpFileBitmap, sizeof(BITMAP), &bitmap);
BYTE *pucInputImage = (BYTE*) bitmap.bmBits; -> Returns NULL
Or
BYTE* pucImage = NULL;
GetBitmapBits(hBmpFileBitmap,nWidth*nHeight*4,(LPVOID)pucImage);
also return NULL in variable pucImage. The only thing which is working is
pBuf=malloc(bmpInfo.bmiHeader.biSizeImage)
GetDIBits(hdc,hBitmap,0,bmpInfo.bmiHeader.biHeight,pBuf,&bmpInfo,DIB_RGB_COLORS);
Here we need to pass the pBuf variable(preallocated with the size of the Image) and GetDIBits copies the data from the bitmpa handle into this pBuf buffer. This is taking 15 ms extra.
As far as I Know there is data transfer happeing during bitblt operation and somehow I feel that I should be able to get away with this extra data transfer avoiding 15ms delay per frame.
One more thing that comes to my mind is because the desktop window needs to be write protected from the user and the HDC hBmpFileDC is derived from the DesktopDC, It might be inheriting the write protection property of the original DC. If this is the case, is there some way to mark this write protection off for the newly created variables (shown below)
HDC hBmpFileDC=CreateCompatibleDC(hDesktopDC);
HBITMAP hBmpFileBitmap=CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);
回答1:
The same problem here, but in VB language. I thinks the problem is that we are creating a Device Independent in memory object, but the source is a DDB (device dependent bitmap), as the desktop bitmap is hosted in the VRAM it must have an VRAM pointer, not RAM, so that way functions like GetObject
and others returns a null pointer
. All the other stuff like .bmwidth
, .bmheight
, .bmtype
, is OK. I am very frustrated by this, because I need to handle the image as a stream for compress + transmission.
来源:https://stackoverflow.com/questions/13228157/unable-to-access-buffer-data-after-screen-capture