我們正在嘗試開發一種解決方案,即需要遠程監視Windows XP計算機的桌面屏幕。屏幕捕獲後無法訪問緩衝區數據
根據我們的經驗,我們發現基於GDI的方法比DirectX前端緩衝區捕獲更快。
在GDI中,我們正在獲取屏幕的句柄,如下所示。
// 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");
該操作保存在給定的路徑,這意味着該對象實際上保持從屏幕上的數據的硬盤驅動器上的m_temp的CImage對象。但在我的應用程序中,我想處理桌面緩衝區中的圖像,我需要圖像數據緩衝區指針。但是當我調用可以返回數據指針的函數m_temp.GetBits()時,我在那裏得到NULL指針。 (I可以看到m_temp保持正確的高度,寬度,位/像素數據valiues但圖像數據緩衝器指針爲NULL)
即使是功能類似於
BITMAP bitmap;
GetObject(hBmpFileBitmap, sizeof(BITMAP), &bitmap);
BYTE *pucInputImage = (BYTE*) bitmap.bmBits; -> Returns NULL
或者
BYTE* pucImage = NULL;
GetBitmapBits(hBmpFileBitmap,nWidth*nHeight*4,(LPVOID)pucImage);
也在變量pucImage中返回NULL。這是工作的唯一的事情是
pBuf=malloc(bmpInfo.bmiHeader.biSizeImage)
GetDIBits(hdc,hBitmap,0,bmpInfo.bmiHeader.biHeight,pBuf,&bmpInfo,DIB_RGB_COLORS);
在這裏,我們需要通過PBUF變量(與圖像的大小預分配)和複製的GetDIBits從數據bitmpa處理到這個PBUF緩衝區。這需要額外15毫秒。
據我所知,在bitblt操作過程中發生數據傳輸,我覺得我應該能夠避免這種額外的數據傳輸,避免每幀15ms的延遲。
我想到的另一件事是因爲桌面窗口需要被用戶寫保護,並且HDC hBmpFileDC是從DesktopDC派生的,它可能會繼承原始DC的寫保護屬性。如果是這樣的話,是有一些方法來這裏紀念這個寫保護關閉新創建的變量(如下圖所示)
HDC hBmpFileDC=CreateCompatibleDC(hDesktopDC);
HBITMAP hBmpFileBitmap=CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);