potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。

C++20&Win API プライマリモニターのハンドル取得&物理モニター情報の列挙

プライマリモニターのハンドルを取得して、その物理モニター情報を列挙するサンプルコードです。

#include <format>
#include <iostream>
#include <string_view>
#include <span>
#include <vector>

#define STRICT
#include <Windows.h>
#include <physicalmonitorenumerationapi.h>
#pragma comment(lib, "dxva2.lib")

inline HMONITOR GetPrimaryMonitorHandle() noexcept
{
    return ::MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);;
}

class PhysicalMonitors final
{
public:
    PhysicalMonitors(HMONITOR monitorHandle)
    {
        DWORD physicalMonitorCount;
        if (!::GetNumberOfPhysicalMonitorsFromHMONITOR(monitorHandle, &physicalMonitorCount))
            return;

        physicalMonitors.resize(physicalMonitorCount);
        if (!::GetPhysicalMonitorsFromHMONITOR(monitorHandle, physicalMonitorCount, physicalMonitors.data()))
            physicalMonitors.clear();
    }

    ~PhysicalMonitors()
    {
        ::DestroyPhysicalMonitors((DWORD)physicalMonitors.size(), physicalMonitors.data());
    }

    auto GetSpan() const noexcept
    {
        return std::span<const PHYSICAL_MONITOR>(physicalMonitors.cbegin(), physicalMonitors.cend());
    }

    HANDLE GetHandleAt(size_t index) const noexcept
    {
        return physicalMonitors[index].hPhysicalMonitor;
    }

    std::wstring_view GetDescriptionAt(size_t index) const noexcept
    {
        return physicalMonitors[index].szPhysicalMonitorDescription;
    }

    DWORD GetCount() const noexcept
    {
        return (DWORD)physicalMonitors.size();
    }

private:
    std::vector<PHYSICAL_MONITOR> physicalMonitors;
};

int main()
{
    std::wcout.imbue(std::locale("Japanese", std::locale::ctype));

    auto primaryMonitorHandle = GetPrimaryMonitorHandle();

    PhysicalMonitors physicalMonitors(primaryMonitorHandle);
    for (auto& physicalMonitor : physicalMonitors.GetSpan())
    {
        std::wcout
            << std::format(L"{:x} - {}",
                (size_t)physicalMonitor.hPhysicalMonitor,
                physicalMonitor.szPhysicalMonitorDescription)
            << std::endl;
    }
}