Я хочу понять DXGI Desktop Duplication. Я много читал, и это код, который я скопировал из частей образца DesktopDuplication на веб-сайте Microsoft. Мой план состоит в том, чтобы получить Buffer или Array из DesktopImage, потому что я хочу создать новую текстуру для другой программы. Я надеюсь, что кто-то может объяснить мне, что я могу сделать, чтобы получить это.
void DesktopDublication::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout)
{
IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
// Get new frame
HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource);
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
*Timeout = true;
}
*Timeout = false;
if (FAILED(hr))
{
}
// If still holding old frame, destroy it
if (m_AcquiredDesktopImage)
{
m_AcquiredDesktopImage->Release();
m_AcquiredDesktopImage = nullptr;
}
// QI for IDXGIResource
hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage));
DesktopResource->Release();
DesktopResource = nullptr;
if (FAILED(hr))
{
}
// Get metadata
if (FrameInfo.TotalMetadataBufferSize)
{
// Old buffer too small
if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize)
{
if (m_MetaDataBuffer)
{
delete[] m_MetaDataBuffer;
m_MetaDataBuffer = nullptr;
}
m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize];
if (!m_MetaDataBuffer)
{
m_MetaDataSize = 0;
Data->MoveCount = 0;
Data->DirtyCount = 0;
}
m_MetaDataSize = FrameInfo.TotalMetadataBufferSize;
}
UINT BufSize = FrameInfo.TotalMetadataBufferSize;
// Get move rectangles
hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(m_MetaDataBuffer), &BufSize);
if (FAILED(hr))
{
Data->MoveCount = 0;
Data->DirtyCount = 0;
}
Data->MoveCount = BufSize / sizeof(DXGI_OUTDUPL_MOVE_RECT);
BYTE* DirtyRects = m_MetaDataBuffer + BufSize;
BufSize = FrameInfo.TotalMetadataBufferSize - BufSize;
// Get dirty rectangles
hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast<RECT*>(DirtyRects), &BufSize);
if (FAILED(hr))
{
Data->MoveCount = 0;
Data->DirtyCount = 0;
}
Data->DirtyCount = BufSize / sizeof(RECT);
Data->MetaData = m_MetaDataBuffer;
}
Data->Frame = m_AcquiredDesktopImage;
Data->FrameInfo = FrameInfo;
}
Если я вас правильно понимаю, вы хотите получить текущее изображение на рабочем столе, скопировать его в частную текстуру и затем отобразить эту частную текстуру в своем окне. Я бы начал с чтения Direct3D 11 и изучения того, как визуализировать сцену, поскольку вам понадобится D3D, чтобы что-то делать с текстурным объектом, полученным из DXGI. это, этот, а также этот могу начать на D3D11. Я также потратил бы некоторое время на чтение исходного кода, из которого вы скопировали код, поскольку он полностью объясняет, как это сделать. Вот это ссылка на полный исходный код для этого образца.
Чтобы фактически получить данные текстуры и визуализировать их, вам нужно сделать следующее:
1). Создайте объект устройства D3D11 и контекст устройства.
2). Напишите и скомпилируйте шейдер Vertex и Pixel для видеокарты, а затем загрузите их в свое приложение.
3). Создайте объект Input Layout и установите его для устройства.
4). Инициализируйте необходимые состояния Blend, Depth-Stencil и Rasterizer для устройства.
5). Создайте текстурный объект и объект Shader Resource View.
6). Получите текстуру дублирования рабочего стола, используя приведенный выше код.
7). использование CopyResource
скопировать данные в вашу текстуру.
8). Рендеринг этой текстуры на экран.
Это захватит все данные, отображаемые на одном из рабочих столов, в вашу текстуру. Это не делает обработку на грязных сторонах рабочего стола. Это не делает обработку на перемещенных регионах. Это простой код для захвата рабочего стола и отображения его в другом месте.
Если вы хотите получить более подробную информацию, прочитайте связанные ресурсы и изучите пример кода, поскольку этот пример в основном выполняет то, что вы просите.
Так как привязать это к моему последнему ответу не совсем правильно, я решил создать второй.
Если вы хотите прочитать данные рабочего стола в файл, вам нужен объект устройства D3D11, объект текстуры с D3D11_USAGE_STAGING
установить флаг и метод преобразования пиксельных данных RGBA текстуры рабочего стола во все, что вам нужно. Основная процедура — это упрощенная версия той, что содержится в моем первоначальном ответе:
1). Создайте объект устройства D3D11 и контекст устройства.
2). Создайте промежуточную текстуру в том же формате, что и на рабочем столе.
3). использование CopyResource
скопировать текстуру рабочего стола в вашу промежуточную текстуру.
4). использование ID3D11DeviceContext::Map()
чтобы получить указатель на данные, содержащиеся в промежуточной текстуре.
Убедитесь, что вы знаете, как Map
работает и убедитесь, что вы можете записывать файлы изображений из одного двоичного потока. В буфере изображений также может быть заполнение, поэтому имейте в виду, что вам может понадобиться отфильтровать это. Кроме того, убедитесь, что вы Unmap
буфер вместо вызова free
Так как данный вам буфер почти наверняка не принадлежит CRT.