屏幕捕获后无法访问缓冲区数据

时间:2012-11-05 08:06:30

标签: windows graphics buffer gdi

我们正在尝试开发一种解决方案,其中需要远程监控来自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指针。 (我可以看到m_temp保持正确的高度,宽度,位/像素数据值,但图像数据缓冲区指针为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变量(预先分配Image的大小),GetDIBits将数据从bitmpa句柄复制到这个pBuf缓冲区。这需要额外15毫秒。

据我所知,在bitblt操作期间发生数据传输,不知怎的,我觉得我应该能够摆脱这种额外的数据传输,避免每帧15ms的延迟。

我想到的另一件事是因为桌面窗口需要对用户进行写保护而HDC hBmpFileDC是从DesktopDC派生的,它可能继承了原始DC的写保护属性。如果是这种情况,是否有某种方法可以为新创建的变量标记此写保护(如下所示)

  HDC         hBmpFileDC=CreateCompatibleDC(hDesktopDC);

  HBITMAP     hBmpFileBitmap=CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);

1 个答案:

答案 0 :(得分:0)

同样的问题在这里,但在VB语言中。我认为问题是我们在内存对象中创建了Device Independent,但源是 DDB (设备相关位图),因为桌面位图是在VRAM中托管的,它必须有一个VRAM指针而不是RAM,因此像GetObject和其他函数一样返回null pointer。所有其他内容(例如.bmwidth.bmheight.bmtype都可以。我对此感到非常沮丧,因为我需要将图像处理为压缩+传输的流。