屏幕截图后无法访问缓冲区数据 [英] Unable to access buffer data after screen capture

查看:178
本文介绍了屏幕截图后无法访问缓冲区数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试开发一种解决方案,即需要远程监控Windows XP计算机的桌面屏幕。根据我们的经验,我们发现基于GDI的方法比DirectX前端缓冲区捕获更快。

在GDI中,我们获得如下屏幕句柄。

  //获取桌面窗口句柄和设备上下文


hDesktopWnd = GetDesktopWindow( );
hDesktopDC = GetDC(hDesktopWnd);


//获取现有DC的句柄并创建一个位图文件对象

HDC hBmpFileDC = CreateCompatibleDC(hDesktopDC);
HBITMAP hBmpFileBitmap = CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);



//将Memory DC中的对象分配给位图并执行bitblt

SelectObject(hBmpFileDC,hBmpFileBitmap);
BitBlt(hBmpFileDC,0,0,nWidth,nHeight,hDesktopDC,0,0,SRCCOPY | CAPTUREBLT);


//将位图句柄分配给一个CImage对象


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位图; 
GetObject(hBmpFileBitmap,sizeof(BITMAP),& bitmap);
BYTE * pucInputImage =(BYTE *)bitmap.bmBits; - >返回NULL

或者

  BYTE * pucImage = NULL; 
GetBitmapBits(hBmpFileBitmap,nWidth * nHeight * 4,(LPVOID)pucImage);

在变量pucImage中也返回NULL。 (bmpInfo.bmiHeader.biSizeImage)
GetDIBits(hdc,hBitmap)

  pBuf = malloc(bmpInfo.bmiHeader.biSizeImage) ,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);


解决方案

同样的问题在VB语言中。我认为问题在于我们在内存对象中创建了一个独立于设备的设备,但源代码是 DDB (依赖于设备的位图),因为桌面位图托管在VRAM中,它必须具有VRAM指针,而不是RAM,所以像 GetObject 等函数返回一个空指针。所有其他的东西,如 .bmwidth .bmheight .bmtype

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);

解决方案

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.

这篇关于屏幕截图后无法访问缓冲区数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆