C++ 在Windows上使用DirectX捕获屏幕

C++ 在Windows上使用DirectX捕获屏幕,c++,c,windows,directx,directx-9,C++,C,Windows,Directx,Directx 9,我正在试验在windows上捕获屏幕的方法,并因此决定最快的方法。最常见的显然是GDI方式。而且它的性能也不错。根据系统负载和静态/非静态屏幕内容,屏幕捕获速率在27-47 fps之间(Windows 7,英特尔i5@2.6GHz,8GB内存) 现在,使用DirectX前端缓冲区方法(使用GetFrontBufferData()API),性能相当,但稍慢一些(我无法达到48 fps) 我浏览了这篇文章:并且尝试了接受答案中建议的方法,使用getRenderTarget()和getRenderTa

我正在试验在windows上捕获屏幕的方法,并因此决定最快的方法。最常见的显然是GDI方式。而且它的性能也不错。根据系统负载和静态/非静态屏幕内容,屏幕捕获速率在27-47 fps之间(Windows 7,英特尔i5@2.6GHz,8GB内存)

现在,使用DirectX前端缓冲区方法(使用GetFrontBufferData()API),性能相当,但稍慢一些(我无法达到48 fps)

我浏览了这篇文章:并且尝试了接受答案中建议的方法,使用getRenderTarget()和getRenderTargetData(),但正如评论中所建议的,我得到的只是一张黑色图像。以下是我的完整代码,包括设备的初始配置:

    IDirect3DSurface9* pRenderTarget=NULL;
    IDirect3DSurface9* pDestTarget=NULL;
    // sanity checks.
    if (g_pd3dDevice == NULL){
      return;
    }
    HRESULT hr;
    // get the render target surface.
    hr = g_pd3dDevice->GetRenderTarget(0, &pRenderTarget);
    // get the current adapter display mode.
    //hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode);

    // create a destination surface.
    hr = g_pd3dDevice->CreateOffscreenPlainSurface(1600, 900, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pDestTarget, NULL);
   //copy the render target to the destination surface.
   hr = g_pd3dDevice->GetRenderTargetData(pRenderTarget, pDestTarget);

   D3DLOCKED_RECT lockedRect;
   hr =pDestTarget->LockRect(&lockedRect,NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY);

    for( int i=0 ; i < 900 ; i++)
    {
        for(int j=0; j < 1600; j++){
            memcpy( (BYTE*) data + i * 1600 * 3 + j * 3, (BYTE*) lockedRect.pBits + i* lockedRect.Pitch + j * 4,  3);
        }
    }
    pDestTarget->UnlockRect();
   // clean up.
   pRenderTarget->Release();
   pDestTarget->Release();
请指出上面代码中的错误。欢迎提出任何建议。我还尝试了GetBackBuffer()API,但无法获取图像数据

编辑:

我的用例是捕获桌面屏幕,这似乎只通过directX使用GetFrontBufferData()完成。GetBackBuffer()/GetRenderTargetData()不是针对这种情况调用的正确API。参考:和


但是,欢迎您提出任何关于更快地捕获桌面屏幕或优化GDI方式的建议。

在截图之前您是否渲染了任何内容

  • GetFrontBufferData-此函数用于获取屏幕数据
  • GetRenderTargetData-此函数用于从渲染目标获取数据

因此,如果您没有渲染任何内容,肯定会得到一张空白图像。

我觉得
GetRenderTarget
将返回设备的后缓冲区。您可能想看看
GetFrontBufferData
函数。正如问题中提到的,我使用了GetFrontBufferData(),它工作正常。但是,与GDI方式相比,性能没有任何提高。我一直在寻找一种更快的方法,如果有的话。我也在写一个截屏应用程序。是我的问题的链接。当我捕获任何游戏时,我会得到一个黑屏,而对于任何其他应用程序,它会返回正确捕获的屏幕。有什么方法可以让它在全屏游戏中发挥作用吗?我在这里可能是断章取义了。我的用例是获取桌面屏幕的数据。那么,您是否认为GetRenderTargetData()不是要调用的正确API。你能详细说明渲染部分吗?请在这里核对你的答案。。因此,GetFrontBufferData()是用于通过DirectX捕获桌面屏幕的唯一API。是的,GetRenderTargetData()用于从应用程序的渲染目标而不是桌面获取数据。
g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION); 
D3DPRESENT_PARAMETERS PresentParams; 
memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS)); 
PresentParams.Windowed = TRUE; 
PresentParams.SwapEffect =D3DSWAPEFFECT_DISCARD;
g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL ,GetDesktopWindow(),D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PresentParams,&g_pd3dDevice);