|
Desktop Duplication API 我用AI试了下,始终是黑屏,没接触过D3D,表面上看不出来哪个环节出问题了
- #include <windows.h>
- #include <d3d11.h>
- #include <dxgi1_2.h>
- #include <wrl/client.h> // 仅用于异常处理,不用于智能指针
- #include <iostream>
- #pragma comment(lib, "d3d11.lib")
- #pragma comment(lib, "dxgi.lib")
- #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } }
- // 窗口尺寸
- const int WINDOW_WIDTH = 800;
- const int WINDOW_HEIGHT = 600;
- // 全局变量
- ID3D11Device* g_pD3DDevice = nullptr;
- ID3D11DeviceContext* g_pD3DDeviceContext = nullptr;
- IDXGIOutputDuplication* g_pDeskDupl = nullptr;
- ID3D11Texture2D* g_pAcquiredDesktopImage = nullptr;
- ID3D11Texture2D* g_pRenderTargetTexture = nullptr;
- ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
- IDXGISwapChain* g_pSwapChain = nullptr;
- // 函数声明
- bool InitializeDirect3D(HWND hwnd);
- bool InitializeDesktopDuplication();
- void CaptureFrame();
- void RenderFrame();
- void Cleanup();
- // 窗口过程函数
- LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch (msg)
- {
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
- // 主函数
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
- {
- // 注册窗口类
- WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, nullptr, nullptr, nullptr, nullptr, L"ScreenCaptureClass", nullptr };
- RegisterClassEx(&wc);
- // 创建窗口
- HWND hwnd = CreateWindow(wc.lpszClassName, L"DirectX Desktop Duplication API Example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, nullptr, nullptr, hInstance, nullptr);
- if (!hwnd)
- {
- std::cerr << "Failed to create window!" << std::endl;
- return -1;
- }
- ShowWindow(hwnd, nCmdShow);
- UpdateWindow(hwnd);
- // 初始化 Direct3D
- if (!InitializeDirect3D(hwnd))
- {
- std::cerr << "Failed to initialize Direct3D!" << std::endl;
- Cleanup();
- return -1;
- }
- // 初始化桌面复制
- if (!InitializeDesktopDuplication())
- {
- std::cerr << "Failed to initialize desktop duplication!" << std::endl;
- Cleanup();
- return -1;
- }
- // 主消息循环
- MSG msg = { 0 };
- while (msg.message != WM_QUIT)
- {
- if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- {
- CaptureFrame();
- RenderFrame();
- }
- }
- Cleanup();
- return static_cast<int>(msg.wParam);
- }
- // 初始化 Direct3D
- bool InitializeDirect3D(HWND hwnd)
- {
- // 创建设备和交换链
- DXGI_SWAP_CHAIN_DESC scd = {};
- scd.BufferCount = 1;
- scd.BufferDesc.Width = WINDOW_WIDTH;
- scd.BufferDesc.Height = WINDOW_HEIGHT;
- scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- scd.BufferDesc.RefreshRate.Numerator = 60;
- scd.BufferDesc.RefreshRate.Denominator = 1;
- scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- scd.OutputWindow = hwnd;
- scd.SampleDesc.Count = 1;
- scd.SampleDesc.Quality = 0;
- scd.Windowed = TRUE;
- HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &scd, &g_pSwapChain, &g_pD3DDevice, nullptr, &g_pD3DDeviceContext);
- if (FAILED(hr))
- {
- std::cerr << "Failed to create device and swap chain!" << std::endl;
- return false;
- }
- // 创建渲染目标视图
- ID3D11Texture2D* pBackBuffer = nullptr;
- hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
- if (FAILED(hr))
- {
- std::cerr << "Failed to get back buffer!" << std::endl;
- return false;
- }
- hr = g_pD3DDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
- SAFE_RELEASE(pBackBuffer);
- if (FAILED(hr))
- {
- std::cerr << "Failed to create render target view!" << std::endl;
- return false;
- }
- g_pD3DDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
- // 设置视口
- D3D11_VIEWPORT vp = {};
- vp.Width = static_cast<float>(WINDOW_WIDTH);
- vp.Height = static_cast<float>(WINDOW_HEIGHT);
- vp.MinDepth = 0.0f;
- vp.MaxDepth = 1.0f;
- vp.TopLeftX = 0;
- vp.TopLeftY = 0;
- g_pD3DDeviceContext->RSSetViewports(1, &vp);
- return true;
- }
- // 初始化桌面复制
- bool InitializeDesktopDuplication()
- {
- // 获取 DXGI 设备
- IDXGIDevice* pDxgiDevice = nullptr;
- HRESULT hr = g_pD3DDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice));
- if (FAILED(hr))
- {
- std::cerr << "Failed to get DXGI device!" << std::endl;
- return false;
- }
- // 获取 DXGI 适配器
- IDXGIAdapter* pDxgiAdapter = nullptr;
- hr = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDxgiAdapter));
- SAFE_RELEASE(pDxgiDevice);
- if (FAILED(hr))
- {
- std::cerr << "Failed to get DXGI adapter!" << std::endl;
- return false;
- }
- // 获取 DXGI 输出
- IDXGIOutput* pDxgiOutput = nullptr;
- hr = pDxgiAdapter->EnumOutputs(0, &pDxgiOutput);
- SAFE_RELEASE(pDxgiAdapter);
- if (FAILED(hr))
- {
- std::cerr << "Failed to get DXGI output!" << std::endl;
- return false;
- }
- // 获取 DXGI 输出1
- IDXGIOutput1* pDxgiOutput1 = nullptr;
- hr = pDxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&pDxgiOutput1));
- SAFE_RELEASE(pDxgiOutput);
- if (FAILED(hr))
- {
- std::cerr << "Failed to get DXGI output1!" << std::endl;
- return false;
- }
- // 创建桌面复制接口
- hr = pDxgiOutput1->DuplicateOutput(g_pD3DDevice, &g_pDeskDupl);
- SAFE_RELEASE(pDxgiOutput1);
- if (FAILED(hr))
- {
- std::cerr << "Failed to create desktop duplication interface!" << std::endl;
- return false;
- }
- return true;
- }
- // 捕获桌面帧
- void CaptureFrame()
- {
- DXGI_OUTDUPL_FRAME_INFO frameInfo;
- IDXGIResource* pDesktopResource = nullptr;
- // 获取桌面帧
- HRESULT hr = g_pDeskDupl->AcquireNextFrame(0, &frameInfo, &pDesktopResource);
- if (FAILED(hr))
- {
- if (hr == DXGI_ERROR_WAIT_TIMEOUT)
- {
- return; // 没有新的帧
- }
- std::cerr << "Failed to acquire next frame!" << std::endl;
- return;
- }
- // 获取桌面纹理
- hr = pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&g_pAcquiredDesktopImage));
- SAFE_RELEASE(pDesktopResource);
- if (FAILED(hr))
- {
- std::cerr << "Failed to get desktop texture!" << std::endl;
- g_pDeskDupl->ReleaseFrame();
- return;
- }
- // 释放帧
- g_pDeskDupl->ReleaseFrame();
- }
- // 渲染帧
- void RenderFrame()
- {
- if (!g_pAcquiredDesktopImage)
- {
- return;
- }
- // 创建渲染目标纹理
- D3D11_TEXTURE2D_DESC desc;
- g_pAcquiredDesktopImage->GetDesc(&desc);
- if (!g_pRenderTargetTexture)
- {
- desc.Width = WINDOW_WIDTH;
- desc.Height = WINDOW_HEIGHT;
- desc.BindFlags = D3D11_BIND_RENDER_TARGET;
- desc.MiscFlags = 0;
- HRESULT hr = g_pD3DDevice->CreateTexture2D(&desc, nullptr, &g_pRenderTargetTexture);
- if (FAILED(hr))
- {
- std::cerr << "Failed to create render target texture!" << std::endl;
- return;
- }
- }
- // 将桌面图像复制到渲染目标纹理
- g_pD3DDeviceContext->CopyResource(g_pRenderTargetTexture, g_pAcquiredDesktopImage);
- // 清除渲染目标
- float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
- g_pD3DDeviceContext->ClearRenderTargetView(g_pRenderTargetView, clearColor);
- // 渲染纹理到窗口
- g_pD3DDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
- g_pD3DDeviceContext->Draw(4, 0);
- // 呈现交换链
- g_pSwapChain->Present(0, 0);
- // 释放桌面图像
- SAFE_RELEASE(g_pAcquiredDesktopImage);
- }
- // 清理资源
- void Cleanup()
- {
- SAFE_RELEASE(g_pRenderTargetTexture);
- SAFE_RELEASE(g_pRenderTargetView);
- SAFE_RELEASE(g_pSwapChain);
- SAFE_RELEASE(g_pDeskDupl);
- SAFE_RELEASE(g_pD3DDeviceContext);
- SAFE_RELEASE(g_pD3DDevice);
- }
复制代码 |
|