Ответы с форумов MSDN

Получение снимков экрана с помощью Desktop Duplication API в Windows

Date: 13.09.2017 15:15:40

Не работает, потому что запроса одного кадра недостаточно. Один кадр не обязан содержать всю необходимую информацию: он может содержать только позицию указателя к примеру, а само изображение идет в следующем кадре. См. https://msdn.microsoft.com/en-us/library/windows/desktop/hh404615(v=vs.85).aspx

Поэтому нужно в цикле сохранять кадры, а потом уже думать, как из них собрать все что нужно. А чтобы получить следующий кадр без исключения, нужно правильно освобождать ресурсы. Как-то так:

ID3D11Texture2D* AcquiredDesktopImage = nullptr;

IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
HBITMAP hBmp;
Int32 num=0;

while(true)
{

	// If still holding old frame, destroy it.
	if (AcquiredDesktopImage)
	{
		AcquiredDesktopImage->Release();
		AcquiredDesktopImage = nullptr;
	}

	// Get new frame.
	hr = DeskDupl->AcquireNextFrame(5000, &FrameInfo, &DesktopResource);
	if (FAILED(hr))
    	{
		if(hr == DXGI_ERROR_ACCESS_LOST)
		{
			Console::WriteLine("DXGI_ERROR_ACCESS_LOST");
		}
		else if(hr==DXGI_ERROR_WAIT_TIMEOUT)
		{
			Console::WriteLine("DXGI_ERROR_WAIT_TIMEOUT");
		}
                else
                {
			Console::WriteLine("Failed to acquire next frame: 0x"+Convert::ToString(hr,16));
		}
		Console::ReadKey();
		continue;
    	}
	

	// Query interface for IDXGIResource.
	hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&AcquiredDesktopImage));
	DesktopResource->Release();
	DesktopResource = nullptr;
	EXIT(hr);

	hBmp = (HBITMAP)ExtractBitmap(AcquiredDesktopImage, pDevice);

	///////////////////////////////////////////////////////////////////////////
	String ^ str="C:\\Images\\Screenshot";
	str+=Convert::ToString(num);
	str+=".bmp";
	Console::WriteLine(Convert::ToString(num));

	//save image to file
	System::Drawing::Bitmap ^ bmp;
	bmp=System::Drawing::Bitmap::FromHbitmap(IntPtr(hBmp));
	bmp->Save(str);
	delete bmp;//no longer need bitmap

	hr = DeskDupl->ReleaseFrame();//no longer need the frame
    	if (FAILED(hr))
    	{
		Console::WriteLine("Failed to release frame");
        	break;
    	}
	
	num++;
	System::Threading::Thread::Sleep(2000);//wait some time for next frame
		
}

Только что вы пытаетесь сделать? Для простого снимания скриншотов не обязательно приплетать DirectX. Можно наверно обойтись средствами GDI, скажем переносом BitBlt из одного DC в другой.



Автор: VadimTagil

Главная страница - Список тем - Репозиторий на GitHub