我们正在尝试开发一种解决方案,其中需要远程监控来自 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 变量(预先分配了图像的大小),GetDIBits 将数据从 bitmpa 句柄复制到这个 pBuf 缓冲区中。这需要额外的 15 毫秒。
据我所知,在 bitblt 操作期间会发生数据传输,不知何故,我觉得我应该能够摆脱这种额外的数据传输,避免每帧 15 毫秒的延迟。
我想到的另一件事是因为桌面窗口需要对用户进行写保护,并且 HDC hBmpFileDC 是从 DesktopDC 派生的,它可能继承了原始 DC 的写保护属性。如果是这种情况,是否有某种方法可以为新创建的变量标记此写保护(如下所示)
HDC hBmpFileDC=CreateCompatibleDC(hDesktopDC);
HBITMAP hBmpFileBitmap=CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);