Как я могу надежно определить, когда «устройство» Direct3D9 сопоставляется с каким «монитором» Windows GDI?

Я пытаюсь получить скриншоты нескольких мониторов, используя и это работает, но я не могу понять, как я могу определить, какой соответствует тому, какой монитор и как его вывод позиционируется на «виртуальном экране» Windows.

Я старался но он всегда получает координаты области просмотра, у которых левая верхняя координата установлена ​​на «0,0» (и правильная ширина и высота), поэтому его нельзя использовать для определения того, какой монитор левый, а какой правый.

Пока я обнаружил, что когда я звоню, мониторы перечисляются в том порядке, в котором перечисляются устройства, когда я звоню, и это можно использовать. Однако я не вижу документации, в которой говорится, гарантирован ли какой-либо порядок перечисления для этих двух функций.

Могу ли я положиться на и с таким же порядком перечисления? Есть ли способ лучше?

1 ответ

Отображение цепочки подкачки устройства Direct3D обратно на монитор оказывается на удивление сложной задачей. Устаревшая версия Direct3D имеетHMONITORкак отметил Рэймонд Чен. Какое-то время вы могли бы использоватьIDXGISwapChain::GetContainingOutputно с тех пор он устарел и больше не работает так, как раньше.

«Рекомендуемое» решение в наши дни выглядит примерно так:

      #include <algorithm>
#include <wrl/client.h>

using Microsoft::WRL::ComPtr;

namespace
{
    inline long ComputeIntersectionArea(
        long ax1, long ay1, long ax2, long ay2,
        long bx1, long by1, long bx2, long by2) noexcept
    {
        return std::max(0l, std::min(ax2, bx2) - std::max(ax1, bx1)) * std::max(0l, std::min(ay2, by2) - std::max(ay1, by1));
    }
}

// Get the retangle bounds of the app window
RECT windowBounds;
if (!GetWindowRect(/* HWND for swapchain window */, &windowBounds))
    // error

const long ax1 = windowBounds.left;
const long ay1 = windowBounds.top;
const long ax2 = windowBounds.right;
const long ay2 = windowBounds.bottom;

ComPtr<IDXGIOutput> bestOutput;
long bestIntersectArea = -1;

ComPtr<IDXGIAdapter> adapter;
for (UINT adapterIndex = 0;
    SUCCEEDED(m_dxgiFactory->EnumAdapters(adapterIndex, adapter.ReleaseAndGetAddressOf()));
    ++adapterIndex)
{
    ComPtr<IDXGIOutput> output;
    for (UINT outputIndex = 0;
        SUCCEEDED(adapter->EnumOutputs(outputIndex, output.ReleaseAndGetAddressOf()));
        ++outputIndex)
    {
        // Get the rectangle bounds of current output.
        DXGI_OUTPUT_DESC desc;
        ThrowIfFailed(output->GetDesc(&desc));
        const auto& r = desc.DesktopCoordinates;

        // Compute the intersection
        const long intersectArea = ComputeIntersectionArea(ax1, ay1, ax2, ay2, r.left, r.top, r.right, r.bottom);
        if (intersectArea > bestIntersectArea)
        {
            bestOutput.Swap(output);
            bestIntersectArea = intersectArea;
        }
    }
}

if (bestOutput)
{
    // Here is the best answer we came up with
}
Другие вопросы по тегам