我正在使用桌面复制 API 从屏幕捕获图像。除了绘制光标之外,一切正常 -IDXGISurface1::GetDC
它返回错误代码 0x887A0001 DXGI_ERROR_INVALID_CALL
(无效参数数据)。此外,前 1-2 张捕获的图像有时会变成空的(填充为黑色)。告诉我如何解决它?
CComPtr<ID3D11Device> pDevice;
CComPtr<IDXGIOutputDuplication> pOutputDuplication;
BOOL Init()
{
CComPtr<IDXGIFactory1> pDxgiFactory;
CComPtr<IDXGIAdapter1> pDxgiAdapter;
CComPtr<IDXGIOutput> pDxgiOutput;
CComPtr<IDXGIOutput1> pDxgiOutput1;
hDC = GetDC(NULL);
CHECK_HR(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pDxgiFactory)));
CHECK_HR(pDxgiFactory->EnumAdapters1(0, &pDxgiAdapter));
CHECK_HR(pDxgiAdapter->EnumOutputs(0, &pDxgiOutput));
CHECK_HR(pDxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&pDxgiOutput1)));
// Supported feature levels.
const D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
D3D_FEATURE_LEVEL d3dFeatLvl;
ID3D11DeviceContext* pImmediateContext = NULL;
CHECK_HR(D3D11CreateDevice(pDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN,
0, 0, featureLevels, ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION, &pDevice,
&d3dFeatLvl, &pImmediateContext));
// Create desktop duplication.
CHECK_HR(pDxgiOutput1->DuplicateOutput(pDevice, &pOutputDuplication));
return TRUE;
}
HBITMAP CaptureScreenshot()
{
DXGI_OUTDUPL_FRAME_INFO DxgiFrameInfo;
IDXGIResource* pDesktopResource;
ID3D11Texture2D* pAcquiredDesktopImage;
AcquireFrame:
if (FAILED(pOutputDuplication->AcquireNextFrame(5000, &DxgiFrameInfo, &pDesktopResource)))
{
return NULL;
}
if (FAILED(pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(&pAcquiredDesktopImage))))
{
pDesktopResource->Release();
return NULL;
}
pDesktopResource->Release();
if (DxgiFrameInfo.LastPresentTime.QuadPart == 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
pAcquiredDesktopImage->Release();
pOutputDuplication->ReleaseFrame();
goto AcquireFrame;
}
HBITMAP hBitmap = ExtractBitmap(hDC, pAcquiredDesktopImage, pDevice);
pAcquiredDesktopImage->Release();
pOutputDuplication->ReleaseFrame();
return hBitmap;
}
使用
IDXGISurface1::GetDC
需要满足文档注释部分中描述的一系列条件,例如交换链是使用标志创建的DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE
、之前没有从中检索过 GDI 上下文等。一般来说,生成的表面并不用于绘图,并且仅使用 GDI 来绘制光标是很奇怪的。此外,您不能忽略内容
DxgiFrameInfo
,包括。更改时间戳,因为只有当图片LastPresentTime
不为 0 并且与之前的值不同时才有意义读取。