桌面复制返回空白图像

时间:2016-02-04 09:35:51

标签: duplicates desktop

我使用了MS桌面复制API获取桌面图片,并获得了一张空白图片。 但是当在调试模式下运行并在AcquireNextFrame之后放置一个断点时,可以重新恢复映像。 我错过了什么?源代码:

#include "stdafx.h"

typedef struct _DX_RESOURCES
{
    ID3D11Device* Device;
    ID3D11DeviceContext* Context;
} DX_RESOURCES;

HRESULT InitializeDX(DX_RESOURCES *res) {

    HRESULT hr = S_OK;

    // Driver types supported
    D3D_DRIVER_TYPE DriverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT NumDriverTypes = ARRAYSIZE(DriverTypes);

    // Feature levels supported
    D3D_FEATURE_LEVEL FeatureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_1
    };
    UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);

    D3D_FEATURE_LEVEL FeatureLevel;

    // Create device
    for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
    {
        hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr, 0, FeatureLevels, NumFeatureLevels,
            D3D11_SDK_VERSION, &res->Device, &FeatureLevel, &res->Context);
        if (SUCCEEDED(hr))
        {
            break;
        }
    }
    return hr;
}

DX_RESOURCES dxRes;

int main()
{

    HRESULT hr = InitializeDX(&dxRes);
    if (FAILED(hr)) {
        return -1;
    }

    D3D11_TEXTURE2D_DESC texdes;

    texdes.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    texdes.BindFlags = 0;
    texdes.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    texdes.Height = 1080;
    texdes.Width = 1920;
    texdes.MiscFlags = 0;
    texdes.MipLevels = 1;
    texdes.ArraySize = 1;
    texdes.SampleDesc.Count = 1;
    texdes.SampleDesc.Quality = 0;
    texdes.Usage = D3D11_USAGE_STAGING;

    ID3D11Texture2D* screenTexture;

    hr = dxRes.Device->CreateTexture2D(&texdes, NULL, &screenTexture);
    if (FAILED(hr))
    {
        return -1;
    }

    IDXGIDevice* DxgiDevice = nullptr;
    hr = dxRes.Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice));
    if (FAILED(hr))
    {
        return -1;
    }

    IDXGIAdapter* DxgiAdapter = nullptr;
    hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter));
    DxgiDevice->Release();
    DxgiDevice = nullptr;
    if (FAILED(hr))
    {
        return -1;
    }

    IDXGIOutput* DxgiOutput = nullptr;
    hr = DxgiAdapter->EnumOutputs(0, &DxgiOutput);
    DxgiAdapter->Release();
    DxgiAdapter = nullptr;
    if (FAILED(hr))
    {
        return -1;
    }

    DXGI_OUTPUT_DESC OutputDesc;
    DxgiOutput->GetDesc(&OutputDesc);

    IDXGIOutput1* DxgiOutput1 = nullptr;
    hr = DxgiOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast<void**>(&DxgiOutput1));
    DxgiOutput->Release();
    DxgiOutput = nullptr;
    if (FAILED(hr))
    {
        return -1;
    }

    IDXGIOutputDuplication* DeskDupl;
    // Create desktop duplication
    hr = DxgiOutput1->DuplicateOutput(dxRes.Device, &DeskDupl);
    DxgiOutput1->Release();
    DxgiOutput1 = nullptr;
    if (FAILED(hr))
    {
        if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
        {
            return -1;
        }
        return -1;
    }

    DXGI_OUTDUPL_FRAME_INFO duplicateFrameInformation;
    IDXGIResource* screenResource;
    ID3D11Texture2D* acquiredDesktopImage;

    DWORD t1 = GetTickCount();
    hr = DeskDupl->AcquireNextFrame(500, &duplicateFrameInformation, &screenResource);
    if (hr == DXGI_ERROR_WAIT_TIMEOUT)
    {
        return 1;
    }
    if (FAILED(hr))
    {
        return -1;
    }

    hr = screenResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&acquiredDesktopImage));
    screenResource->Release();
    screenResource = nullptr;
    if (FAILED(hr))
    {
        return -1;
    }

    ID3D11DeviceContext* context;
    dxRes.Device->GetImmediateContext(&context);
    context->CopyResource(screenTexture, acquiredDesktopImage);

    IDXGISurface* screenSurface;
    hr = screenTexture->QueryInterface(__uuidof(IDXGISurface), reinterpret_cast<void **>(&screenSurface));
    if (FAILED(hr))
    {
        return -1;
    }

    DXGI_SURFACE_DESC desc;
    screenSurface->GetDesc(&desc);

    DXGI_MAPPED_RECT rect;
    hr = screenSurface->Map(&rect, DXGI_MAP_READ);
    if (FAILED(hr))
    {
        return -1;
    }

    FILE *fp;
    fp = fopen("d:\\test.rgba", "wb");
    fwrite(rect.pBits, 1, 1920 * 1080 * 4, fp);
    fclose(fp);
    screenSurface->Unmap();

    acquiredDesktopImage->Release();
    acquiredDesktopImage = nullptr;

    DWORD t2 = GetTickCount() - t1;

    printf("OK\n");

    return t2;
}

1 个答案:

答案 0 :(得分:1)

afert AcquireNextFrame,应检查[duplicateFrameInformation]的输出值。

// Get metadata
if (duplicateFrameInformation.TotalMetadataBufferSize)
{
    ....do some process
}