思路:
- 通过
EnumDisplayMonitors
枚举所有的显示器 - 通过
GetMonitorInfo
获取设备分辨率 - 通过
EnumDisplaySettings
获取设备刷新频率 - 通过
EnumDisplayDevices
获取edid
数据在注册表中的位置 - 解析
edid
获取设备尺寸,厂商,名称等信息 - 通过CreateDC获取指定屏幕的HDC
edit参考:EDID标准简介,EDID的简介和解析
下面是实现代码:文章来源:https://www.toymoban.com/news/detail-517204.html
typedef struct stMonitorInfo
{
TCHAR szfirm[4];//厂商
TCHAR szname[18];//显示器名称
unsigned long resolution_width, resolution_heght;//分辨率
unsigned long device_width_cm, device_heght_cm;//设备尺寸
unsigned long frequency;//设备刷新频率
stMonitorInfo()
{
memset(this, 0, sizeof(stMonitorInfo));
}
}stMonitorInfo;
枚举设备并且获取设备信息文章来源地址https://www.toymoban.com/news/detail-517204.html
BOOL CALLBACK _MonitorEnumProc(HMONITOR hMonitor, // handle to display monitor
HDC hdcMonitor, // handle to monitor DC
LPRECT lprcMonitor, // monitor intersection rectangle
LPARAM dwData // data
)
{
std::vector<stMonitorInfo> *pvec_monitor = (std::vector<stMonitorInfo>*) dwData;
MONITORINFOEX miex;
miex.cbSize = sizeof(miex);
if (GetMonitorInfo(hMonitor, &miex))
{
stMonitorInfo monitor_info;
monitor_info.resolution_width = miex.rcMonitor.right - miex.rcMonitor.left;
monitor_info.resolution_heght = miex.rcMonitor.bottom - miex.rcMonitor.top;
//monitor_info.device_millimeters_width = GetDeviceCaps(hdcMonitor, HORZSIZE);
//monitor_info.device_millimeters_heght = GetDeviceCaps(hdcMonitor, VERTSIZE);
DEVMODE devMode = { 0 };
devMode.dmSize = sizeof(devMode);
devMode.dmDriverExtra = sizeof(0);
if (EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &devMode))
{
if (devMode.dmFields & DM_DISPLAYFREQUENCY)
{
monitor_info.frequency = devMode.dmDisplayFrequency;
}
}
//为了防止edid不对,采取HDC方式获取
HDC hdc = CreateDC(NULL, miex.szDevice, NULL, NULL);
if (hdc)
{
get_display_physical_size(hdc, monitor_info.device_width_cm, monitor_info.device_heght_cm);
DeleteDC(hdc);
}
DISPLAY_DEVICE data = { 0 };
data.cb = sizeof(data);
if (EnumDisplayDevices(miex.szDevice, 0, &data, EDD_GET_DEVICE_INTERFACE_NAME))
{
//DeviceID "\\\\?\\DISPLAY#DELA07A#5&30f41049&0&UID4352#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}" char[128]
//开始解析
printf("Monitor DeviceID:%s\r\n", data.DeviceID);
std::vector<std::string> vec_data;
split(data.DeviceID, "#", vec_data);
if (vec_data.size() >= 3)
{
char szKey[1024] = "";
_stprintf_s(szKey, 1024, "SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\%s\\%s\\Device Parameters", vec_data[1].c_str(), vec_data[2].c_str());
std::vector<BYTE> edid;
if (Registry::Read(HKEY_LOCAL_MACHINE, szKey, "EDID", edid))
{
//这里应该计算校验和如果校验和不对则忽略
if (monitor_info.device_width_cm == 0 && monitor_info.device_heght_cm == 0)
{
monitor_info.device_width_cm = edid[0x15];
monitor_info.device_heght_cm = edid[0x16];
}
//给一个默认名称,方式edid数据里面没有名称
lstrcpyn(monitor_info.szname, vec_data[1].c_str(), 260);
//避免大小端问题
std::bitset<8> bits0(edid[8]);
std::bitset<8> bits1(edid[9]);
std::string strBits = bits0.to_string() + bits1.to_string();
std::bitset<5> prd0(strBits, 1);
std::bitset<5> prd1(strBits, 6);
std::bitset<5> prd2(strBits, 11);
ULONG lval0 = prd0.to_ulong();
ULONG lval1 = prd1.to_ulong();
ULONG lval2 = prd2.to_ulong();
monitor_info.szfirm[0] = TCHAR('A') + lval0 - 1;
monitor_info.szfirm[1] = TCHAR('A') + lval1 - 1;
monitor_info.szfirm[2] = TCHAR('A') + lval2 - 1;
//获取显示器名称
std::vector<int> vec = { 0x36, 0x48, 0x5a, 0x6c };
for (int i = 0; i < vec.size(); ++i)
{
int nindex = vec[i];
if (edid[nindex] == 0x00 && edid[nindex + 1] == 0x00 && edid[nindex + 2] == 0x00 && edid[nindex +3] == 0xfc)
{
std::string str((char *)&edid[nindex + 4], 14);
//删除\0 \n 0x20
if (str[0] == 0) str = str.substr(1);
while (!str.empty())
{
if (str[str.size() - 1] == 0x20 || str[str.size() - 1] == '\n')
{
str = str.substr(0, str.size() - 1);
continue;
}
break;
}
lstrcpy(monitor_info.szname, str.c_str());
}
}
}
}
}
pvec_monitor->push_back(monitor_info);
}
return TRUE;
}
void get_monitor_info(std::vector<stMonitorInfo> &vec_monitor)
{
EnumDisplayMonitors(NULL, NULL, _MonitorEnumProc, (LPARAM)&vec_monitor);
}
void get_display_resolution(int &width, int &height)
{
static int Width{ GetSystemMetrics(SM_CXSCREEN) };
static int Heigth{ GetSystemMetrics(SM_CYSCREEN) };
width = Width;
height = Heigth;
}
void get_display_physical_size(HDC hdc,unsigned int &width_millimeters, unsigned int &height_millimeters)
{
bool bRelease = false;
if (hdc == NULL)
{
bRelease = true;
hdc = GetDC(NULL);
}
width_millimeters = GetDeviceCaps(hdc, HORZSIZE)/10;
height_millimeters = GetDeviceCaps(hdc, VERTSIZE)/10;
if (bRelease)
ReleaseDC(NULL, hdc);
}
到了这里,关于C++ 获取多显示器设备信息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!