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;
}
相关推荐
阿巴~阿巴~1 小时前
深入解析C++ STL链表(List)模拟实现
开发语言·c++·链表·stl·list
旺小仔.2 小时前
双指针和codetop复习
数据结构·c++·算法
jingfeng5142 小时前
C++ STL-string类底层实现
前端·c++·算法
郝学胜-神的一滴2 小时前
基于C++的词法分析器:使用正则表达式的实现
开发语言·c++·程序人生·正则表达式·stl
网硕互联的小客服3 小时前
Apache 如何支持SHTML(SSI)的配置方法
运维·服务器·网络·windows·php
etcix3 小时前
implement copy file content to clipboard on Windows
windows·stm32·单片机
许泽宇的技术分享4 小时前
Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析
windows·自动化·.net
努力努力再努力wz4 小时前
【c++深入系列】:万字详解模版(下)
java·c++·redis
非凡ghost5 小时前
AMS PhotoMaster:全方位提升你的照片编辑体验
windows·学习·信息可视化·软件需求
瓦特what?5 小时前
关于C++的#include的超超超详细讲解
java·开发语言·数据结构·c++·算法·信息可视化·数据挖掘