Skip to content

Match the monitor index to the enumeration order of EnumDisplayMonitors() #232

@yeongjet

Description

@yeongjet

I wanna capture screen output by indices from virtual-display-cli after adding monitor, but the index in virtual display cli is not match the order of EnumDisplayMonitors().
Without this feature I have to use EnumDisplayMonitors() to enum all display monitors to choose indices, any other resolvetion?

#include "screen.h"
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h>

using Microsoft::WRL::ComPtr;
// capture screen output by index
int capture(
    ComPtr<ID3D11Texture2D> &outTexture,
    D3D11_TEXTURE2D_DESC *outDesc,
    UINT screenIndex) // I want it from virtual-display-cli output
{
    ComPtr<ID3D11Device> device = nullptr;
    ComPtr<ID3D11DeviceContext> context = nullptr;
    D3D_FEATURE_LEVEL featureLevel;
    HRESULT hr = D3D11CreateDevice(
        nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
        D3D11_SDK_VERSION, &device, &featureLevel, &context);
    if (FAILED(hr))
    {
        return -1;
    }
    ComPtr<IDXGIDevice> dxgiDevice;
    device.As(&dxgiDevice);
    ComPtr<IDXGIAdapter> dxgiAdapter;
    dxgiDevice->GetAdapter(&dxgiAdapter);
    ComPtr<IDXGIOutput> dxgiOutput;
  // the first param is match the order of  EnumDisplayMonitors(), which means screenIndex from cli can't be passed
    hr = dxgiAdapter->EnumOutputs(screenIndex, &dxgiOutput);
    if (FAILED(hr))
    {
        return -10; 
    }
    ComPtr<IDXGIOutput1> dxgiOutput1;
    dxgiOutput.As(&dxgiOutput1);
    ComPtr<IDXGIOutputDuplication> deskDupl;
    hr = dxgiOutput1->DuplicateOutput(device.Get(), &deskDupl);
    if (FAILED(hr))
    {
        return -2;
    }
    DXGI_OUTDUPL_FRAME_INFO frameInfo;
    ComPtr<IDXGIResource> desktopResource;
    hr = deskDupl->AcquireNextFrame(1000, &frameInfo, &desktopResource);
    if (FAILED(hr))
    {
        return -3;
    }
    ComPtr<ID3D11Texture2D> acquiredDesktopImage;
    desktopResource.As(&acquiredDesktopImage);
    D3D11_TEXTURE2D_DESC desc = {};
    acquiredDesktopImage->GetDesc(&desc);
    if (outDesc)
        *outDesc = desc;
    D3D11_TEXTURE2D_DESC descStaging = desc;
    descStaging.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    descStaging.Usage = D3D11_USAGE_STAGING;
    descStaging.BindFlags = 0;
    descStaging.MiscFlags = 0;
    ComPtr<ID3D11Texture2D> stagingTex;
    hr = device->CreateTexture2D(&descStaging, nullptr, &stagingTex);
    if (FAILED(hr))
    {
        deskDupl->ReleaseFrame();
        return -4;
    }
    context->CopyResource(stagingTex.Get(), acquiredDesktopImage.Get());
    deskDupl->ReleaseFrame();
    outTexture = stagingTex;
    return 0;
}

//get screens(with resolutions info) by indices from cli
std::vector<Screen> getScreens(const std::vector<int> &indices)
{
    std::vector<Screen> screens;
    int monitorCount = 0;
    std::vector<std::pair<uint16_t, uint16_t>> resolutions;
// the order is not match the indices from cli
    EnumDisplayMonitors(
        nullptr, nullptr,
        [](HMONITOR hMon, HDC hdcMon, LPRECT lprcMon, LPARAM pData) -> BOOL
        {
            auto res = reinterpret_cast<std::vector<std::pair<uint16_t, uint16_t>> *>(pData);
            MONITORINFOEX mi;
            mi.cbSize = sizeof(mi);
            if (GetMonitorInfo(hMon, &mi))
            {
       // output:  "Monitor name:  \\.\DISPLAY1", there is no monitor name in cli output, I can't use it to find the target monitor
                printf("Monitor name: %s\n", mi.szDevice); 
                DEVMODE dm;
                dm.dmSize = sizeof(dm);
                if (EnumDisplaySettings(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm))
                {
                    res->emplace_back(static_cast<uint16_t>(dm.dmPelsWidth), static_cast<uint16_t>(dm.dmPelsHeight));
                }
            }
            return TRUE;
        },
        reinterpret_cast<LPARAM>(&resolutions));

    for (int idx : indices)
    {
        if (idx >= 0 && idx < static_cast<int>(resolutions.size()))
        {
            screens.push_back({idx,
                               resolutions[idx].first,
                               resolutions[idx].second});
        }
    }
    return screens;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions