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;
}