Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法从后缓冲区(DirectX9)捕获数据_C++_Visual Studio 2008_Visual C++_Gdi_Directx 9 - Fatal编程技术网

C++ 无法从后缓冲区(DirectX9)捕获数据

C++ 无法从后缓冲区(DirectX9)捕获数据,c++,visual-studio-2008,visual-c++,gdi,directx-9,C++,Visual Studio 2008,Visual C++,Gdi,Directx 9,我试图找到最快的截图方法。到目前为止,我已经发现GDI或DirectX都可以使用。使用GDI我可以在35毫秒内捕获屏幕,而使用DirectX前端缓冲区平均需要73毫秒。我想要比这更快的方法。为此,在DirectX中捕获后缓冲区似乎是一种很好的方法。我正在使用以下代码执行相同的操作: D3DDISPLAYMODE ddm; D3DPRESENT_PARAMETERS d3dpp; if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION)

我试图找到最快的截图方法。到目前为止,我已经发现GDI或DirectX都可以使用。使用GDI我可以在35毫秒内捕获屏幕,而使用DirectX前端缓冲区平均需要73毫秒。我想要比这更快的方法。为此,在DirectX中捕获后缓冲区似乎是一种很好的方法。我正在使用以下代码执行相同的操作:

    D3DDISPLAYMODE  ddm;
    D3DPRESENT_PARAMETERS   d3dpp;

    if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
    {
        ErrorMessage("Unable to Create Direct3D ");
        return E_FAIL;
    }

    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm)))
    {
        ErrorMessage("Unable to Get Adapter Display Mode");
        return E_FAIL;
    }

    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));

    d3dpp.Windowed=WINDOW_MODE;
    d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    d3dpp.BackBufferFormat=ddm.Format;
    d3dpp.BackBufferHeight=nDisplayHeight=gScreenRect.bottom =ddm.Height;
    d3dpp.BackBufferWidth=nDisplayWidth=gScreenRect.right =ddm.Width;
    d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
//  d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
    d3dpp.SwapEffect=D3DSWAPEFFECT_COPY;
    d3dpp.hDeviceWindow=hWnd;
    d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
    d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;

    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&g_pd3dDevice)))
    {
        ErrorMessage("Unable to Create Device");
        return E_FAIL;
    }

    if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &g_pSurface, NULL)))
    {
        ErrorMessage("Unable to Create Surface");
        return E_FAIL;
    }

g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&g_pSurface);
D3DXSaveSurfaceToFile("d:\\v\\temp.bmp",D3DXIFF_BMP,g_pSurface,NULL,NULL);

问题是,输出文件的大小为5MB,但在输出中只显示黑色。在相同的代码中,如果使用GetFrontBufferData,则可以成功捕获屏幕。我做错什么了吗?请帮帮我

您无法从backbuffer捕获屏幕快照

frontbuffer-backbuffer关系的工作方式如下:清除backbuffer,然后将场景一次绘制一次调用。一旦准备就绪,它将使用frontbuffer翻转,这样frontbuffer将获得要显示的最终图像,而backbuffer将再次被擦除


从理论上讲,backbuffer会有您想要的数据,但我不相信您能够可靠地获得这种状态。frontbuffer是为完成此任务而设计的。

以下是我截图的方式:

IDirect3DSurface9 *offscreenSurface = 0;
d3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &offscreenSurface);
D3DXSaveSurfaceToFile( filename, D3DXIFF_BMP, offscreenSurface, 0, 0 )

请注意,此代码是在调用
Present
之前运行的。

是否检查:除非我遗漏了什么,否则您实际上没有绘制任何东西,因此您没有要捕获的内容。@mots:是的,我有。我也在尝试,因为作者无法让它工作。你可以使用后缓冲区来捕获你自己的窗口。然而,你必须先画一些东西。如果您试图捕获操作系统屏幕,那么DX就不是办法。还请注意,使用复制语义交换前后缓冲区的速度较慢。在调用Present之前,请先阅读后台缓冲区。@Eisen:我可以考虑使用GDI的两种方法。第一种方法是将屏幕捕获到剪贴板,然后读取剪贴板。您可以在这里找到一个示例(应该可以工作,但不是亲自测试):第二种方法是使用GetWindowDC和NULL获取整个屏幕的DC,然后继续创建您自己的兼容DC BitBlt int该DC并从中读取位图。我明白了。。但在codeproject上,有人说可以使用后缓冲区捕获屏幕。我正在开发一个性能关键型应用程序,因此需要一种最佳方法。我正在探索可能的解决方案。后缓冲区不会被擦除-他指定了复制语义。他什么也没画。我试着用你建议的方法。它返回所有内容的黑屏。是我问题的链接。我尝试按照您的建议更改代码:IDirect3DSurface9*pbackBuffer=0;d3ddev->GetBackBuffer(0、0、D3DBACKBUFFER_TYPE_MONO和pbackBuffer);D3DXSaveSurfaceToFile(L“screen.bmp”,D3DXIFF_bmp,pbackBuffer,NULL,NULL);pbackBuffer->Release();但现在它为每个应用程序返回一个黑色图像。以前的代码在其他地方运行良好,但只是没有捕获全屏游戏。我做错了什么?所以我注意到我的截图是在调用Present()之前拍摄的,而在你的例子中,截图是在之后拍摄的。这可能与你的问题有关。