Win32 显示器信息获取, 显示模式设置

CDisplayUtils.h

cpp 复制代码
#pragma once
#include <wtypesbase.h>
#include <tchar.h>
#include <vector>
#include <string>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

typedef struct _MONITOR_DESC_INFO
{
    HMONITOR hMonitor;
    RECT rect;
    bool bPrimary;
    _tstring strDevice;

    _MONITOR_DESC_INFO() :hMonitor(NULL), rect{ 0 }, bPrimary(false) {}

}MONITOR_DESC_INFO;

typedef struct _DISPLAY_MODE_INFO
{
    DWORD dmPelsWidth;
    DWORD dmPelsHeight;
    DWORD dmDisplayFrequency;

    _DISPLAY_MODE_INFO() :dmPelsWidth(0), dmPelsHeight(0), dmDisplayFrequency(0) {}

}DISPLAY_MODE_INFO;

enum DisplayOrientation
{
    DoDefault = DMDO_DEFAULT,
    Do90 = DMDO_90,
    Do180 = DMDO_180,
    Do270 = DMDO_270,
};

class CDisplayUtils
{
public:

    //
    // @brief: 获取显示监视器信息
    // @param: void                             无
    // @ret: std::vector<MONITOR_DESC_INFO>     显示监视器信息列表
    static std::vector<MONITOR_DESC_INFO> GetDisplayMonitorInfos();

    //
    // @brief: 获取主显示监视器信息
    // @param: void                             无
    // @ret: MONITOR_DESC_INFO                  显示监视器信息
    static MONITOR_DESC_INFO GetPrimaryDisplayMonitorInfo();

    //
    // @brief: 获取显示监视器信息
    // @param: iDevNum                          显示设备索引(从0开始)
    // @ret: std::vector<DISPLAY_MODE_INFO>     显示监视器显示模式列表
    static std::vector<DISPLAY_MODE_INFO> GetDisplayMode(DWORD iDevNum = 0);

    //
    // @brief: 获取主显示监视器信息
    // @param: iDevNum                          显示设备索引(从0开始)
    // @ret: std::vector<DISPLAY_MODE_INFO>     显示监视器显示模式列表
    static std::vector<DISPLAY_MODE_INFO> GetPrimaryDisplayMode();

    //
    // @brief: 获取主显示监视器索引
    // @param: void                             无
    // @ret: DWORD                              主显示监视器索引
    static DWORD GetPrimaryMonitorIndex();

    //
    // @brief: 获取当前活动屏幕宽高
    // @param: nW                               屏幕宽度
    // @param: nH                               屏幕高度
    // @ret: bool                               操作结果
    static bool GetCurrentSize(DWORD& nW, DWORD& nH);

    //
    // @brief: 设置当前活动屏幕宽高
    // @param: nW                               屏幕宽度
    // @param: nH                               屏幕高度
    // @ret: bool                               操作结果
    static bool SetCurrentSize(DWORD nW, DWORD nH);

    //
    // @brief: 获取当前活动屏幕旋转方向
    // @param: nOri                             屏幕旋转方向
    // @ret: bool                               操作结果
    static bool GetCurrentOrientation(DisplayOrientation& nOri);

    //
    // @brief: 设置当前活动屏幕旋转方向
    // @param: nOri                             屏幕旋转方向
    // @ret: bool                               操作结果
    static bool SetCurrentOrientation(DisplayOrientation nOri);

    //
    // @brief: 设置当前活动屏幕自动旋转
    // @param: bEnable                          是否启用自动旋转
    // @ret: bool                               操作结果
    static bool SetCurrentAutoRotation(bool bEnable = false);

    //
    // @brief: 获取当前活动屏幕自动旋转
    // @param: bEnable                          是否启用自动旋转
    // @ret: bool                               操作结果
    static bool GetCurrentAutoRotation(bool& bEnable);

    //
    // @brief: 设置当前活动屏幕旋转横向
    // @param: bFlipped                         是否翻转
    // @ret: bool                               操作结果
    static bool SetCurrentLandscape(bool bFlipped = false);

    //
    // @brief: 设置当前活动屏幕旋转纵向
    // @param: bFlipped                         是否翻转
    // @ret: bool                               操作结果
    static bool SetCurrentPortrait(bool bFlipped = false);

private:

    //
    // @brief: 检查当前活动屏幕是否为横屏
    // @param: nW                               屏幕宽度
    // @param: nH                               屏幕高度
    // @param: nOri                             屏幕旋转方向
    // @ret: bool                               操作结果
    static bool IsCurrentLandscape(DWORD nW, DWORD nH, DWORD nOri);
};

CDisplayUtils.cpp

cpp 复制代码
#include "CDisplayUtils.h"

#pragma warning(disable:4100)
#pragma comment(lib, "Advapi32.lib")

#define SCREEN_AUTOROTATION     R"(SOFTWARE\Microsoft\Windows\CurrentVersion\AutoRotation)"
#define HKLM                    HKEY_LOCAL_MACHINE

std::vector<MONITOR_DESC_INFO> CDisplayUtils::GetDisplayMonitorInfos()
{
    std::vector<MONITOR_DESC_INFO> vMonitorInfos;

    if (!::EnumDisplayMonitors(NULL, NULL, [](HMONITOR hMonitor,
        HDC hDC,
        LPRECT lpRect,
        LPARAM lparam) -> BOOL {
            MONITORINFOEX monitorInfo;
            monitorInfo.cbSize = sizeof(MONITORINFOEX);
            GetMonitorInfo(hMonitor, &monitorInfo);

            MONITOR_DESC_INFO info;
            info.hMonitor = hMonitor;
            info.rect = *lpRect;
            info.bPrimary = false;
            info.strDevice = monitorInfo.szDevice;
            if (0 == info.rect.left && 0 == info.rect.top)
            {
                info.bPrimary = true;
            }

            std::vector<MONITOR_DESC_INFO>* pInfos = (std::vector<MONITOR_DESC_INFO>*)lparam;
            pInfos->push_back(info);
            return TRUE;

        }, (LPARAM)&vMonitorInfos))
    {
    }

    return vMonitorInfos;
}

MONITOR_DESC_INFO CDisplayUtils::GetPrimaryDisplayMonitorInfo()
{
    std::vector<MONITOR_DESC_INFO> vInfos = GetDisplayMonitorInfos();
    MONITOR_DESC_INFO emptyInfo;

    for (size_t i = 0; i < vInfos.size(); i++)
    {
        if (vInfos[i].bPrimary)
        {
            return vInfos[i];
        }
    }

    return emptyInfo;
}

std::vector<DISPLAY_MODE_INFO> CDisplayUtils::GetDisplayMode(DWORD iDevNum)
{
    std::vector<DISPLAY_MODE_INFO> vInfos;
    DISPLAY_DEVICE DisplayDevice = { 0 };
    DisplayDevice.cb = sizeof(DISPLAY_DEVICE);

    if (::EnumDisplayDevices(NULL, iDevNum, &DisplayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
    {
        DEVMODE dm = { 0 };
        dm.dmSize = sizeof(dm);
        DWORD    iModeNum = 0;

        DWORD lastDmPelsWidth = 0;
        DWORD lastDmPelsHeight = 0;
        DWORD lastDmDisplayFrequency = 0;

        while (::EnumDisplaySettings(DisplayDevice.DeviceName, iModeNum++, &dm))
        {
            if (!(lastDmPelsWidth == dm.dmPelsWidth &&
                lastDmPelsHeight == dm.dmPelsHeight &&
                lastDmDisplayFrequency == dm.dmDisplayFrequency
                )
                )
            {
                DISPLAY_MODE_INFO info;
                info.dmPelsWidth = dm.dmPelsWidth;
                info.dmPelsHeight = dm.dmPelsHeight;
                info.dmDisplayFrequency = dm.dmDisplayFrequency;
                vInfos.push_back(info);

                lastDmPelsWidth = dm.dmPelsWidth;
                lastDmPelsHeight = dm.dmPelsHeight;
                lastDmDisplayFrequency = dm.dmDisplayFrequency;
            }
        }
    }

    return vInfos;
}

std::vector<DISPLAY_MODE_INFO> CDisplayUtils::GetPrimaryDisplayMode()
{
    return GetDisplayMode(GetPrimaryMonitorIndex());
}

DWORD CDisplayUtils::GetPrimaryMonitorIndex()
{
    DWORD dwMonitorIndex = 0;

    std::vector<MONITOR_DESC_INFO> descInfos = GetDisplayMonitorInfos();
    for (size_t i = 0; i < descInfos.size(); i++)
    {
        if (descInfos[i].bPrimary)
        {
            dwMonitorIndex = i;
        }
    }

    return dwMonitorIndex;
}

bool CDisplayUtils::GetCurrentSize(DWORD& nW, DWORD& nH)
{
    DEVMODE dm = { 0 };
    dm.dmSize = sizeof(dm);

    if (::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
    {
        nW = dm.dmPelsWidth;
        nH = dm.dmPelsHeight;
        return true;
    }

    return false;
}

bool CDisplayUtils::SetCurrentSize(DWORD nW, DWORD nH)
{
    DEVMODE dm = { 0 };
    dm.dmSize = sizeof(dm);

    if (::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
    {
        dm.dmDisplayFixedOutput = DMDFO_DEFAULT;
        dm.dmPelsWidth = nW;
        dm.dmPelsHeight = nH;

        long lRet = ::ChangeDisplaySettings(&dm, 0);
        if (DISP_CHANGE_SUCCESSFUL == lRet)
        {
            return true;
        }
    }

    return false;
}

bool CDisplayUtils::GetCurrentOrientation(DisplayOrientation& nOri)
{
    DEVMODE dm = { 0 };
    dm.dmSize = sizeof(dm);

    if (::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
    {
        nOri = (DisplayOrientation)dm.dmDisplayOrientation;
        return true;
    }

    return false;
}

bool CDisplayUtils::SetCurrentOrientation(DisplayOrientation nOri)
{
    DEVMODE dm = { 0 };
    dm.dmSize = sizeof(dm);

    if (::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
    {
        dm.dmDisplayOrientation = nOri;

        long lRet = ::ChangeDisplaySettings(&dm, CDS_UPDATEREGISTRY);
        if (DISP_CHANGE_SUCCESSFUL == lRet)
        {
            return true;
        }
    }

    return false;
}

bool CDisplayUtils::SetCurrentAutoRotation(bool bEnable)
{
    LSTATUS lr = ERROR_SUCCESS;
    DWORD dwData = bEnable ? 1 : 0;

    lr = ::RegSetKeyValue(HKLM, 
        _T(SCREEN_AUTOROTATION), 
        _T(R"(Enable)"), 
        REG_DWORD, 
        &dwData, 
        sizeof(DWORD)
    );

    if (ERROR_SUCCESS != lr)
    {
        return false;
    }

    return ERROR_SUCCESS == lr;
}

bool CDisplayUtils::GetCurrentAutoRotation(bool& bEnable)
{
    LSTATUS lr = ERROR_SUCCESS;
    DWORD dwData = 0;
    DWORD cbSize = sizeof(dwData);

    lr = ::RegGetValue(HKLM, 
        _T(SCREEN_AUTOROTATION),
        _T(R"(Enable)"), 
        RRF_RT_REG_DWORD | RRF_ZEROONFAILURE, 
        NULL, 
        &dwData, 
        &cbSize
    );

    if (ERROR_SUCCESS != lr)
    {
        return false;
    }

    bEnable = (1 == dwData ? true : false);

    return ERROR_SUCCESS == lr;
}

bool CDisplayUtils::IsCurrentLandscape(DWORD nW, DWORD nH, DWORD nOri)
{
    if (nW > nH && (DMDO_DEFAULT == nOri || DMDO_180 == nOri))
    {
        return true;
    }

    if (nW < nH && (DMDO_90 == nOri || DMDO_270 == nOri))
    {
        return true;
    }

    return false;
}

bool CDisplayUtils::SetCurrentLandscape(bool bFlipped)
{
    DEVMODE dm = { 0 };
    DWORD dwW = 0;
    DWORD dwH = 0;

    dm.dmSize = sizeof(dm);

    if (::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
    {
        dwW = dm.dmPelsWidth;
        dwH = dm.dmPelsHeight;

        // 检查是否横屏
        if (IsCurrentLandscape(dwW, dwH, dm.dmDisplayOrientation))
        {
            if (dwW < dwH)
            {
                dm.dmPelsWidth = dwH;
                dm.dmPelsHeight = dwW;
            }

            dm.dmDisplayOrientation = bFlipped ? DMDO_180 : DMDO_DEFAULT;
        }
        else
        {
            if (dwW < dwH)
            {
                dm.dmPelsWidth = dwH;
                dm.dmPelsHeight = dwW;
            }

            dm.dmDisplayOrientation = bFlipped ? DMDO_90 : DMDO_270;
        }

        long lRet = ::ChangeDisplaySettings(&dm, 0);
        if (DISP_CHANGE_SUCCESSFUL == lRet)
        {
            return true;
        }
    }

    return false;
}

bool CDisplayUtils::SetCurrentPortrait(bool bFlipped)
{
    DEVMODE dm = { 0 };
    DWORD dwW = 0;
    DWORD dwH = 0;

    dm.dmSize = sizeof(dm);

    if (::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
    {
        dwW = dm.dmPelsWidth;
        dwH = dm.dmPelsHeight;

        // 检查是否横屏
        if (IsCurrentLandscape(dwW, dwH, dm.dmDisplayOrientation))
        {
            if (dwW >= dwH)
            {
                dm.dmPelsWidth = dwH;
                dm.dmPelsHeight = dwW;
            }

            dm.dmDisplayOrientation = bFlipped ? DMDO_270 : DMDO_90;
        }
        else
        {
            if (dwW >= dwH)
            {
                dm.dmPelsWidth = dwH;
                dm.dmPelsHeight = dwW;
            }

            dm.dmDisplayOrientation = bFlipped ? DMDO_180 : DMDO_DEFAULT;
        }

        long lRet = ::ChangeDisplaySettings(&dm, 0);
        if (DISP_CHANGE_SUCCESSFUL == lRet)
        {
            return true;
        }
    }

    return false;
}

main.cpp

cpp 复制代码
#include <locale.h>
#include <tchar.h>
#include "Win32Utils/CTimeUtils.h"
#include "Win32Utils/CProcessUtils.h"
#include "Win32Utils/CDisplayUtils.h"

int _tmain(int argc, LPCTSTR argv[])
{
    ::setlocale(LC_ALL, "");

    MONITOR_DESC_INFO info = CDisplayUtils::GetPrimaryDisplayMonitorInfo();
    std::vector<MONITOR_DESC_INFO> monitorDesc = CDisplayUtils::GetDisplayMonitorInfos();
    std::vector<DISPLAY_MODE_INFO> displayMode = CDisplayUtils::GetPrimaryDisplayMode();

    return 0;
}
相关推荐
唐诺5 小时前
几种广泛使用的 C++ 编译器
c++·编译器
冷眼看人间恩怨6 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
红龙创客6 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin6 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
Clockwiseee7 小时前
php伪协议
windows·安全·web安全·网络安全
yuanbenshidiaos7 小时前
c++---------数据类型
java·jvm·c++
十年一梦实验室8 小时前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
taoyong0018 小时前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
这是我588 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
唐宋元明清21888 小时前
.NET 阻止系统睡眠/息屏
windows·电源