Сделайте скриншот полноэкранного приложения DirectX - PullRequest
14 голосов
/ 26 декабря 2009

Это поражает меня. DirectX обходит все и напрямую обращается к драйверу устройства, поэтому GDI и другие обычные методы не будут работать - если Aero не отключен (или недоступен), все, что появляется, это черный прямоугольник в левом верхнем углу экрана. Я попробовал то, что другие предложили на нескольких форумах, используя DirectX, чтобы получить резервный буфер и сохранить его, но я получаю тот же результат:

device-> GetFrontBufferData (0, surface); D3DXSaveSurfaceToFile ("имя файла", D3DXIFF_BMP, поверхность, NULL, NULL);

Можно ли получить снимок экрана с другим полноэкранным приложением DirectX, когда Aero включен?

Ответы [ 7 ]

22 голосов
/ 26 декабря 2009

Взгляните на Объезд .

Используя Detours, вы можете обрабатывать вызовы типа Direct3DCreate9, IDirect3D9::CreateDevice и IDirect3D9::Present, в которых вы выполняете операции, необходимые для настройки, а затем делаете захват кадра.

8 голосов
/ 15 мая 2010

Вот пример C # перехвата объектов IDirect3DDevice9 через внедрение DLL и перехват функций с помощью EasyHook (например, Microsoft Detours). Это похоже на работу FRAPS.

Это позволяет вам захватывать экран в оконном / полноэкранном режиме и использует задний буфер, который намного быстрее, чем пытается извлечь данные из переднего буфера.

Небольшая вспомогательная DLL-библиотека C ++ используется для определения методов объекта IDirect3DDevice9, подключаемых во время выполнения.

Обновление: для DirectX 10/11, см. Снимок экрана и наложения для D3D 9, 10 и 11

3 голосов
/ 26 декабря 2009

Это фрагмент кода, который я сейчас использовал в качестве теста, похоже, он работает.

ширина и высота - это размер ЭКРАНА в оконном режиме, а не окон. Так что для меня они установлены в 1280 x 1024, а не в окно, к которому я рендуюсь.

Вам также необходимо заменить mEngine-> getDevice () каким-либо способом получения вашего IDirect3DDevice9. Я просто вставил этот код в случайное d3d-приложение, которое мне нужно было сделать, чтобы его было проще тестировать. Но я могу подтвердить, что он фиксирует как выходные данные этого приложения, так и другое приложение d3d, запущенное одновременно.

О, я предположил, что это D3D9, как вы не сказали, я не уверен насчет d3d10 или 11

IDirect3DSurface9* surface;
mEngine->getDevice()->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8,     D3DPOOL_SCRATCH, &surface, NULL);
mEngine->getDevice()->GetFrontBufferData(0, surface);
D3DXSaveSurfaceToFile("c:\\tmp\\output.jpg", D3DXIFF_JPG, surface, NULL, NULL);
surface->Release();
2 голосов
/ 02 октября 2012

После ответа J99 я заставил код работать как для оконного, так и для полноэкранного режима. Это также сделано в D3D9.

  IDirect3DSurface9* surface;
  D3DDISPLAYMODE mode;
  pDev->GetDisplayMode(0, &mode); // pDev is my *IDirect3DDevice
  // we can capture only the entire screen,
  // so width and height must match current display mode
  pDev->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
  if(pDev->GetFrontBufferData(0, surface)==D3D_OK)
  {
    if(bWindowed) // a global config variable
    {
      // get client area in desktop coordinates
      // this might need to be changed to support multiple screens
      RECT r;
      GetClientRect(hWnd, &r); // hWnd is our window handle
      POINT p = {0, 0};
      ClientToScreen(hWnd, &p);
      SetRect(&r, p.x, p.y, p.x+r.right, p.y+r.bottom);
      D3DXSaveSurfaceToFile(szFilename, D3DXIFF_JPG, surface, NULL, &r);
    }
    else
      D3DXSaveSurfaceToFile(szFilename, D3DXIFF_JPG, surface, NULL, NULL);
  }
  surface->Release();

Похоже, что параметры формата и пула CreateOffscreenPlainSurface должны совпадать.

2 голосов
/ 29 декабря 2009

Вот некоторые обсуждения того, как работает Fraps. Это не просто.

http://www.woodmann.com/forum/archive/index.php/t-11023.html

Любой трюк, который пытается прочитать передний буфер с другого устройства DirectX, я подозреваю, может работать только из-за удачи неинициализированной памяти.

2 голосов
/ 26 декабря 2009

Существует программа с открытым исходным кодом, такая как fraps: taksi , но выглядит устаревшей

1 голос
/ 10 ноября 2012

Возможно, вы захотите взглянуть на мой проект Investigo.

Используется прокси-библиотека DirectX для перехвата функций DirectX API.

Там уже есть код для снимков экрана во время звонка в Present. Хотя это еще не доступно из пользовательского интерфейса. Вы должны быть в состоянии легко включить код, хотя.

http://www.codeproject.com/Articles/448756/Introducing-Investigo-Using-a-Proxy-DLL-and-embedd

...