C++ 获取多显示器设备信息

这篇具有很好参考价值的文章主要介绍了C++ 获取多显示器设备信息。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

思路:

  1. 通过EnumDisplayMonitors枚举所有的显示器
  2. 通过GetMonitorInfo获取设备分辨率
  3. 通过EnumDisplaySettings获取设备刷新频率
  4. 通过EnumDisplayDevices获取edid数据在注册表中的位置
  5. 解析edid获取设备尺寸,厂商,名称等信息
  6. 通过CreateDC获取指定屏幕的HDC

edit参考:EDID标准简介,EDID的简介和解析

下面是实现代码:

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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt怎么获取显示器分辨率

    您可以使用QScreen类来获取当前显示器的分辨率。以下是一个示例代码: 上面的程序将输出主屏幕的分辨率。 如果您有多个显示器并且需要获取其中一个的分辨率,则可以使用QDesktopWidget类。下面是一个示例代码: 上面的程序将输出第2个屏幕的分辨率。请注意,屏幕编号从

    2024年02月13日
    浏览(53)
  • 远程ubuntu 20.04的nvidia驱动自动更新,机器重启后,ToDesk或者向日葵等远程连接黑屏,解决办法:为远程设备添加虚拟显示器

    第4部分的解决办法,很多网友反映,会导致 物理显示器不能用 !请仔细阅读文章里的解决办法。 请仔细 阅读第5部分的特别注意事项, 虚拟显示器会和物理显示器冲突。让虚拟显示器和物理显示器同时工作的解决办法,请参考第5部分, 合并虚拟显示器和物理显示器的 xo

    2024年01月16日
    浏览(64)
  • 中柏 EZpad 8 Windows 平板电脑 |驱动备份|系统优化|不能调节显示器亮度|进入Bios/uefi 快捷键 |蓝牙扫描不到设备|CPU占用过高解决方案

              之前一直使用的这个平板,但是有个很严重的问题就是性能实在太差了,每次都是CPU百分百,Mem 百分之50% 这个结果真的很意外, 但是又无可奈何,后面花时间做了一些优化包括 进程限制  启动优化  内存页面优化  但结果都不尽人意,一启动程序就卡顿 ..........  中间又

    2024年02月09日
    浏览(125)
  • 【Flutter】Flutter 使用 device_info_plus 获取设备的制造商、型号等信息

    【Flutter】Flutter 使用 device_info_plus 获取设备的制造商、型号等信息 在这篇博客中,我将为你介绍一个非常实用的 Flutter 插件: device_info_plus 。这个插件可以帮助我们获取设备的详细信息,如制造商、型号等,以及应用程序正在运行的 Android 或 iOS 版本。 本文的重点如下: 如

    2024年02月05日
    浏览(47)
  • ManjaroLinux扩展显示器,连接显示器。

    如何设置多显示器的显示 在这里可以使用xrandr来进行设置。 1.插入显示器的接口 这时,我们把刚买的显示器的接口接到显示器上面,确保显示器和笔记本直接的连接没有问题。 2.查看显示器是否连接成功 我们输入命令 回车后可以看到如下扩展显示器的设备接口名称以及可显

    2024年02月11日
    浏览(55)
  • 显示器原理(1):CRT显示器

    大家好,这个系列将会从历史、参数角度来详细讲解显示器及跟显示器有关的技术。 首先,我们先列出一个目录,方便大家理解显示器的参数在哪里起效,这里列出的都是常见的,不常见的我们也会讲,这里就不列出了 这张表格在后几期会用到,我会详细讲解色域、刷新率

    2024年02月09日
    浏览(118)
  • 解决 Ubuntu 外接显示器后,显示器不亮

    目录 原因 解决办法 step1: 修改软件源 step2:查看可安装的驱动版本 step3:安装推荐版本的驱动(recommended) step4:查看是否安装成功 step5:重启电脑,发现外接显示器已亮。 没有装显卡驱动。 step1: 修改软件源 打开 应用程序 —— 软件和更新,在 Ubuntu 软件 界面,点下载自的

    2024年02月09日
    浏览(68)
  • 2023年2K显示器推荐 | 有什么好用的2K显示器?

    开玩笑,如果是同价位来说,当然还是选Nano IPS了,画质好延迟低,妥妥的电竞显示器首选。关键你还是主玩LOL平时看电影,对延迟的要求远低于画质吧,所以TN屏就不用考虑了。Nano IPS的色彩表现的确是IPS屏中的佼佼者,毕竟是色域都可以达到95%以上的DCI-P3,可以产生更加鲜

    2024年02月11日
    浏览(56)
  • Mac 连接显示器,外接显示器不出影像

    1. 现象 转换头,连接线已正确连接; 显示器电源等也亮,且是已有视频信号的状态; 查看设置–显示器,里面也显示识别出已连接外接显示器 2. 解决办法 显示器支持的 最高刷新率 与 系统设置的刷新率 不一致的 2.1 打开 设置 – 显示器 2.2 点击底部 显示器设置 2.3 重点在这

    2024年02月11日
    浏览(104)
  • ubuntu外接显示器、不识别笔记本显示器

    如题:ubuntu外接显示器、不识别笔记本显示器 双屏幕,笔记本外接显示器HDMI,然后安装Nvidia显卡驱动,之后重启笔记本显示器无法识别,只能使用外接显示器了。 中文网站找遍了都没有解决方案,然后用英文搜索,得到这篇文章解决了问题: Internal laptop screen not detected wh

    2024年02月05日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包