Я пытаюсь найти самый быстрый способ сделать скриншот. До сих пор я выяснил, что можно использовать GDI или DirectX. С помощью GDI я могу захватить экран за 35 мс, а при использовании буфера DirectX Front это занимает в среднем 73 мс. Я хочу еще более быстрый метод, чем этот. Для этой цели захват Back Buffer в 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);
Проблема в том, что размер выходного файла составляет 5 МБ, но в выводе отображается только черный цвет. Находясь в том же коде, если я использую GetFrontBufferData, я могу успешно захватить экран. Я делаю что-то не так? Пожалуйста, помогите мне..
Вот как я делаю скриншот:
IDirect3DSurface9 *offscreenSurface = 0;
d3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &offscreenSurface);
D3DXSaveSurfaceToFile( filename, D3DXIFF_BMP, offscreenSurface, 0, 0 )
Обратите внимание, что этот код запускается до Present
называется.
Вы не можете сделать снимок экрана с заднего буфера.
Отношение фронт-буфер-буфер-буфер работает следующим образом: буфер-буфер очищается, а затем сцена обращается к нему по одному вызову отрисовки за раз. Как только он готов, он переворачивается с помощью переднего буфера, так что передний буфер получает окончательное изображение для отображения, в то время как задний буфер снова стирается.
Теоретически есть момент, когда в бэкбуфере есть нужные вам данные, но я не верю, что вы можете надежно получить это состояние. Фронтбуфер предназначен для этой задачи.