如何获取windows系统连接显示器的名称列表

 本文根据windows系统提供的设备api, 配合注册表访问接口 获取电脑所连接显示器的厂商名称列表,代码如下:

#include <iostream>  
#include <vector>
#include <string>
#include <stdio.h>
#include <bitset>
#include <windows.h>
#include <winreg.h>
void get_display_physical_size(HDC hdc, unsigned long &width_millimeters, unsigned long &height_millimeters);



static void Stringsplit(const std::string& str, const std::string& split, std::vector<std::string>& res)
{
	char* strc = new char[str.size() + 1];
	strcpy(strc, str.c_str());   // 将str拷贝到 char类型的strc中
	char* temp = strtok(strc, split.c_str());
	while (temp != NULL)
	{
		res.push_back(std::string(temp));
		temp = strtok(NULL, split.c_str());	// 下一个被分割的串
	}
	delete[] strc;
}



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;

		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;

			Stringsplit(data.DeviceID, "#", vec_data);

			if (vec_data.size() >= 3)
			{
				char szKey[1024] = "";
				sprintf(szKey, "SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\%s\\%s\\Device Parameters", vec_data[1].c_str(), vec_data[2].c_str());

				//std::vector<BYTE> edid;
				BYTE edid[1024] = { 0 };
				HKEY hKey;
				long lRet;
				lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey);

				unsigned long dwSize = sizeof(edid);
				if(ERROR_SUCCESS == RegQueryValueEx(
							hKey,            // handle to key
							"EDID",  // value name
							NULL,   // reserved
							NULL,       // type buffer
							(LPBYTE)edid,        // data buffer
							&dwSize      // size of data buffer
						))
				{
					//这里应该计算校验和如果校验和不对则忽略
					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_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 long &width_millimeters, unsigned long &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);
}

void get_monitor_info(std::vector<stMonitorInfo> &vec_monitor)
{
	EnumDisplayMonitors(NULL, NULL, _MonitorEnumProc, (LPARAM)&vec_monitor);
}

int main() {
	std::vector<stMonitorInfo> vec_monitor;
	get_monitor_info(vec_monitor);
	for(int i = 0; i < vec_monitor.size(); i++)
	{
		printf("m%d:%s-%s\n",i,vec_monitor[i].szfirm,vec_monitor[i].szname);
	}

	return 0;
}

代码依赖库文件windows系统 “Dxva2.lib”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值