1、包含必要的头文件:
#include <d3d11.h>
#include <dxgi1_2.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
2、创建一个D3D设备和设备上下文。
ID3D11Device* pDevice = nullptr;
ID3D11DeviceContext* pImmediateContext = nullptr;
D3D_FEATURE_LEVEL featureLevel;
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
D3D11_SDK_VERSION, &pDevice, &featureLevel, &pImmediateContext);
if (FAILED(hr))
{
// 处理错误
return;
}
3、获取屏幕的输出(Output)。
IDXGIDevice* pDXGIDevice = nullptr;
hr = pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDXGIDevice));
if (FAILED(hr))
{
// 处理错误
return;
}
IDXGIAdapter* pAdapter = nullptr;
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pAdapter));
if (FAILED(hr))
{
// 处理错误
pDXGIDevice->Release();
return;
}
IDXGIOutput* pOutput = nullptr;
hr = pAdapter->EnumOutputs(0, &pOutput);
if (FAILED(hr))
{
// 处理错误
pAdapter->Release();
pDXGIDevice->Release();
return;
}
4、获取输出的描述(Description)。
DXGI_OUTPUT_DESC outputDesc;
hr = pOutput->GetDesc(&outputDesc);
if (FAILED(hr))
{
// 处理错误
pOutput->Release();
pAdapter->Release();
pDXGIDevice->Release();
return;
}
5、创建一个DXGI输出的工厂对象,并获取它的接口。
IDXGIFactory2* pFactory = nullptr;
hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&pFactory));
if (FAILED(hr))
{
// 处理错误
pOutput->Release();
pAdapter->Release();
pDXGIDevice->Release();
return;
}
6、创建一个DXGI资源。
IDXGISurface* pSurface = nullptr;
hr = pOutput->DuplicateOutput(pDXGIDevice, &pSurface);
if (FAILED(hr))
{
// 处理错误
pFactory->Release();
pOutput->Release();
pAdapter->Release();
pDXGIDevice->Release();
return;
}
7、将资源拷贝到CPU上并保存为图像文件。
D3D11_TEXTURE2D_DESC desc;
pSurface->GetDesc(&desc);
D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = desc.Width;
textureDesc.Height = desc.Height;
textureDesc.Format = desc.Format;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Usage = D3D11_USAGE_STAGING;
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
ID3D11Texture2D* pTexture = nullptr;
hr = pDevice->CreateTexture2D(&textureDesc, nullptr, &pTexture);
if (FAILED(hr))
{
// 处理错误
pSurface->Release();
pFactory->Release();
pOutput->Release();
pAdapter->Release();
pDXGIDevice->Release();
return;
}
pImmediateContext->CopyResource(pTexture, pSurface);
D3D11_MAPPED_SUBRESOURCE mappedResource;
hr = pImmediateContext->Map(pTexture, 0, D3D11_MAP_READ, 0, &mappedResource);
if (FAILED(hr))
{
// 处理错误
pTexture->Release();
pSurface->Release();
pFactory->Release();
pOutput->Release();
pAdapter->Release();
pDXGIDevice->Release();
return;
}
unsigned char* pbmBits = static_cast<unsigned char*>(mappedResource.pData);
// 在这里保存屏幕截图为文件
SaveBitmapToFile(pbmBits, desc.Width, desc.Height, “c:/screenshot.bmp”)
pImmediateContext->Unmap(pScreenTexture, 0);
pTexture->Release();
pSurface->Release();
pFactory->Release();
pOutput->Release();
pAdapter->Release();
pDXGIDevice->Release();
8、创建一个函数来保存位图到文件。
HRESULT SaveBitmapToFile(char* bmBits, int bmWidth, int bmHeight, const wchar_t* filePath)
{
HRESULT result = S_OK;
// 创建位图文件头
BITMAPFILEHEADER fileHeader;
fileHeader.bfType = 0x4D42; // "BM"
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmWidthBytes * bmHeight;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 创建位图信息头
BITMAPINFOHEADER infoHeader;
infoHeader.biSize = sizeof(BITMAPINFOHEADER);
infoHeader.biWidth = bmWidth;
infoHeader.biHeight = -bmHeight;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 32;
infoHeader.biCompression = BI_RGB;
infoHeader.biSizeImage = 0;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
// 创建文件并写入位图数据
HANDLE fileHandle = CreateFileW(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle != INVALID_HANDLE_VALUE)
{
DWORD bytesWritten = 0;
WriteFile(fileHandle, &fileHeader, sizeof(BITMAPFILEHEADER), &bytesWritten, NULL);
WriteFile(fileHandle, &infoHeader, sizeof(BITMAPINFOHEADER), &bytesWritten, NULL);
WriteFile(fileHandle, bmBits, bmWidth * bmp.bmHeight * 4, &bytesWritten, NULL);
CloseHandle(fileHandle);
}
else
{
result = E_FAIL;
}
return result;
}