Как я могу надежно определить, когда «устройство» Direct3D9 сопоставляется с каким «монитором» Windows GDI?
Я пытаюсь получить скриншоты нескольких мониторов, используя
Я старался
Пока я обнаружил, что когда я звоню, мониторы перечисляются в том порядке, в котором перечисляются устройства, когда я звоню, и это можно использовать. Однако я не вижу документации, в которой говорится, гарантирован ли какой-либо порядок перечисления для этих двух функций.
Могу ли я положиться на
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
}