获取显示器信息
This commit is contained in:
		| @@ -1,9 +1,22 @@ | ||||
| #include <stdafx.h> | ||||
| #include <cstdio> | ||||
| #include <iphlpapi.h> | ||||
| #include <dxgi.h> | ||||
| #include <vector> | ||||
| #include <windows.h> | ||||
| #include <cfgmgr32.h> | ||||
| #include <comdef.h> | ||||
| #include <Wbemidl.h> | ||||
| #include <io.h> | ||||
| #include <fcntl.h> | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
|  | ||||
| #include "SysInfoUtil.h" | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
|  | ||||
| void SysInfoUtil::GetMacByGetAdaptersInfo(char* outMAC) const | ||||
| { | ||||
|     ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); | ||||
| @@ -39,3 +52,250 @@ void SysInfoUtil::GetMacByGetAdaptersInfo(char* outMAC) const | ||||
|     } | ||||
|     free(pAdapterInfo); | ||||
| } | ||||
|  | ||||
| int SysInfoUtil::GetInfoByQueryDisplayConfig() | ||||
| { | ||||
|     wcout << L"=====GetInfoByQueryDisplayConfig start=====" << endl; | ||||
|     std::vector<DISPLAYCONFIG_PATH_INFO> paths; | ||||
|     std::vector<DISPLAYCONFIG_MODE_INFO> modes; | ||||
|     UINT32 flags = QDC_ONLY_ACTIVE_PATHS; | ||||
|     LONG isError = ERROR_INSUFFICIENT_BUFFER; | ||||
|  | ||||
|     UINT32 pathCount, modeCount; | ||||
|     isError = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount); | ||||
|     if (isError) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     // Allocate the path and mode arrays | ||||
|     paths.resize(pathCount); | ||||
|     modes.resize(modeCount); | ||||
|     // Get all active paths and their modes | ||||
|     isError = QueryDisplayConfig(flags, &pathCount, paths.data(), &modeCount, modes.data(), nullptr); | ||||
|     // The function may have returned fewer paths/modes than estimated | ||||
|     paths.resize(pathCount); | ||||
|     modes.resize(modeCount); | ||||
|     if (isError) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|     // For each active path | ||||
|     int len = paths.size(); | ||||
|     for (int i = 0; i < len; i++) | ||||
|     { | ||||
|         // Find the target (monitor) friendly name | ||||
|         DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; | ||||
|         targetName.header.adapterId = paths[i].targetInfo.adapterId; | ||||
|         targetName.header.id = paths[i].targetInfo.id; | ||||
|         targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; | ||||
|         targetName.header.size = sizeof(targetName); | ||||
|         isError = DisplayConfigGetDeviceInfo(&targetName.header); | ||||
|  | ||||
|         if (isError) | ||||
|         { | ||||
|             return 0; | ||||
|         } | ||||
|         wcout << "monitorFriendlyDeviceName:" << targetName.monitorFriendlyDeviceName << endl; | ||||
|         wcout << "monitorDevicePath:" << targetName.monitorDevicePath << endl; | ||||
|     } | ||||
|     wcout << "=====GetInfoByQueryDisplayConfig end=====" << endl; | ||||
| } | ||||
| int SysInfoUtil::GetInfoByCfgmgr() | ||||
| { | ||||
|     wcout << "GetInfoByCfgmgr start" << endl; | ||||
|     DEVINST devInstRoot; | ||||
|     CONFIGRET cr = CM_Locate_DevNode(&devInstRoot, NULL, 0); | ||||
|     if (cr != CR_SUCCESS) { | ||||
|         // 处理错误 | ||||
|         wcout << "GetInfoByCfgmgr error" << cr << endl; | ||||
|         return 0; | ||||
|     } | ||||
|     DEVINST devInstMonitor; | ||||
|     cr = CM_Get_Child(&devInstMonitor, devInstRoot, 0); | ||||
|     while (cr == CR_SUCCESS) { | ||||
|         // 在这里处理监视器设备 | ||||
|         WCHAR displayName[1024]; | ||||
|         ULONG displayNameSize = sizeof(displayName); | ||||
|  | ||||
|         cr = CM_Get_DevNode_Registry_Property(devInstMonitor, CM_DRP_FRIENDLYNAME, NULL, displayName, &displayNameSize, 0); | ||||
|         if (cr == CR_SUCCESS) { | ||||
|             // displayName 包含显示名称 | ||||
|             wcout << "displayName:" << displayName << endl; | ||||
|         } | ||||
|  | ||||
|         WCHAR hardwareId[1024]; | ||||
|         ULONG hardwareIdSize = sizeof(hardwareId); | ||||
|  | ||||
|         cr = CM_Get_DevNode_Registry_Property(devInstMonitor, CM_DRP_HARDWAREID, NULL, hardwareId, &hardwareIdSize, 0); | ||||
|         if (cr == CR_SUCCESS) { | ||||
|             // hardwareId 包含硬件ID | ||||
|             wcout << "hardwareId:" << hardwareId << endl; | ||||
|         } | ||||
|         // 继续遍历下一个设备 | ||||
|         cr = CM_Get_Sibling(&devInstMonitor, devInstMonitor, 0); | ||||
|     } | ||||
|     wcout << "GetInfoByCfgmgr end" << endl; | ||||
| } | ||||
|  | ||||
| int SysInfoUtil::GetInfoByEnumDisplayDevices() | ||||
| { | ||||
|     wcout << "=====GetInfoByEnumDisplayDevices start=====" << endl; | ||||
|     DISPLAY_DEVICE displayDevice; | ||||
|     displayDevice.cb = sizeof(DISPLAY_DEVICE); | ||||
|     DWORD deviceIndex = 0; | ||||
|  | ||||
|     while (EnumDisplayDevices(NULL, deviceIndex, &displayDevice, 0)) | ||||
|     { | ||||
|         std::wcout << "Display Device Name: " << displayDevice.DeviceName << std::endl; | ||||
|         std::wcout << "Display Device String: " << displayDevice.DeviceString << std::endl; | ||||
|         std::wcout << "Display Device ID: " << displayDevice.DeviceID << std::endl; | ||||
|         std::wcout << "Display Device Key: " << displayDevice.DeviceKey << std::endl; | ||||
|         deviceIndex++; | ||||
|     } | ||||
|  | ||||
|     wcout << "=====GetInfoByEnumDisplayDevices end=====" << endl; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void SysInfoUtil::GetInfoByEnumDisplayMonitors() | ||||
| { | ||||
|     wcout << "=====GetInfoByEnumDisplayMonitors start=====" << endl; | ||||
|     // 枚举显示器 | ||||
|     EnumDisplayMonitors(NULL, NULL, [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { | ||||
|         MONITORINFOEX monitorInfo; | ||||
|         monitorInfo.cbSize = sizeof(MONITORINFOEX); | ||||
|         if (GetMonitorInfo(hMonitor, &monitorInfo)) { | ||||
|             // 输出友好名称 | ||||
|             wcout << "szDevice:" << monitorInfo.szDevice << endl; | ||||
|             wcout << "right:" << monitorInfo.rcMonitor.right << endl; | ||||
|             wcout << "bottom:" << monitorInfo.rcMonitor.bottom << endl; | ||||
|         } | ||||
|         return TRUE; | ||||
|         }, 0); | ||||
|     wcout << "=====GetInfoByEnumDisplayMonitors end=====" << endl; | ||||
| } | ||||
|  | ||||
| int SysInfoUtil::GetInfoByWMI() | ||||
| { | ||||
|     wcout << "=====GetInfoByWMI start=====" << endl; | ||||
|     _setmode(_fileno(stdout), _O_U16TEXT); | ||||
|     HRESULT hr; | ||||
|  | ||||
|     hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); | ||||
|     if (FAILED(hr)) { | ||||
|         std::wcerr << L"COM 初始化失败!" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     hr = CoInitializeSecurity( | ||||
|         nullptr, | ||||
|         -1, | ||||
|         nullptr, | ||||
|         nullptr, | ||||
|         RPC_C_AUTHN_LEVEL_DEFAULT, | ||||
|         RPC_C_IMP_LEVEL_IMPERSONATE, | ||||
|         nullptr, | ||||
|         EOAC_NONE, | ||||
|         nullptr); | ||||
|  | ||||
|     if (FAILED(hr)) { | ||||
|         CoUninitialize(); | ||||
|         std::wcerr << L"CoInitializeSecurity 失败!" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     IWbemLocator* pLocator = nullptr; | ||||
|     hr = CoCreateInstance( | ||||
|         CLSID_WbemLocator, | ||||
|         nullptr, | ||||
|         CLSCTX_INPROC_SERVER, | ||||
|         IID_IWbemLocator, | ||||
|         reinterpret_cast<void**>(&pLocator)); | ||||
|  | ||||
|     if (FAILED(hr)) { | ||||
|         CoUninitialize(); | ||||
|         std::wcerr << L"CoCreateInstance 失败!" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     IWbemServices* pServices = nullptr; | ||||
|     hr = pLocator->ConnectServer( | ||||
|         _bstr_t(L"ROOT\\CIMV2"), | ||||
|         nullptr, | ||||
|         nullptr, | ||||
|         0, | ||||
|         0, | ||||
|         0, | ||||
|         0, | ||||
|         &pServices); | ||||
|  | ||||
|     pLocator->Release(); | ||||
|  | ||||
|     if (FAILED(hr)) { | ||||
|         CoUninitialize(); | ||||
|         std::wcerr << L"ConnectServer 失败!" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     hr = CoSetProxyBlanket( | ||||
|         pServices, | ||||
|         RPC_C_AUTHN_WINNT, | ||||
|         RPC_C_AUTHZ_NONE, | ||||
|         nullptr, | ||||
|         RPC_C_AUTHN_LEVEL_CALL, | ||||
|         RPC_C_IMP_LEVEL_IMPERSONATE, | ||||
|         nullptr, | ||||
|         EOAC_NONE); | ||||
|  | ||||
|     if (FAILED(hr)) { | ||||
|         pServices->Release(); | ||||
|         CoUninitialize(); | ||||
|         std::wcerr << L"CoSetProxyBlanket 失败!" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     IEnumWbemClassObject* pEnum = nullptr; | ||||
|     hr = pServices->ExecQuery( | ||||
|         bstr_t("WQL"), | ||||
|         bstr_t("SELECT * FROM Win32_DesktopMonitor"), | ||||
|         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, | ||||
|         nullptr, | ||||
|         &pEnum); | ||||
|  | ||||
|     if (FAILED(hr)) { | ||||
|         pServices->Release(); | ||||
|         CoUninitialize(); | ||||
|         std::wcerr << L"ExecQuery 失败!" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     IWbemClassObject* pClassObject = nullptr; | ||||
|     ULONG uReturn = 0; | ||||
|  | ||||
|     while (pEnum->Next(WBEM_INFINITE, 1, &pClassObject, &uReturn) == 0) { | ||||
|         VARIANT vtDeviceID; | ||||
|         VARIANT vtScreenWidth; | ||||
|         VARIANT vtScreenHeight; | ||||
|         VARIANT vtModelName; | ||||
|  | ||||
|         hr = pClassObject->Get(L"DeviceID", 0, &vtDeviceID, 0, 0); | ||||
|         hr = pClassObject->Get(L"ScreenWidth", 0, &vtScreenWidth, 0, 0); | ||||
|         hr = pClassObject->Get(L"ScreenHeight", 0, &vtScreenHeight, 0, 0); | ||||
|         hr = pClassObject->Get(L"MonitorType", 0, &vtModelName, 0, 0); | ||||
|  | ||||
|         if (SUCCEEDED(hr) && vtDeviceID.vt == VT_BSTR && vtScreenWidth.vt == VT_I4 && vtScreenHeight.vt == VT_I4 && vtModelName.vt == VT_BSTR) { | ||||
|             std::wcout << L"设备名称: " << vtDeviceID.bstrVal << std::endl; | ||||
|             std::wcout << L"分辨率: " << vtScreenWidth.lVal << L"x" << vtScreenHeight.lVal << std::endl; | ||||
|             std::wcout << L"型号: " << vtModelName.bstrVal << std::endl; | ||||
|         } | ||||
|  | ||||
|         pClassObject->Release(); | ||||
|     } | ||||
|  | ||||
|     pEnum->Release(); | ||||
|     pServices->Release(); | ||||
|     CoUninitialize(); | ||||
|     wcout << L"=====GetInfoByWMI end=====" << endl; | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,22 @@ | ||||
| #pragma once | ||||
|  | ||||
| #pragma comment(lib, "IPHLPAPI.lib") | ||||
| #pragma comment(lib, "wbemuuid.lib") | ||||
|  | ||||
| class SysInfoUtil | ||||
| { | ||||
| public: | ||||
|     void GetMacByGetAdaptersInfo(char* outMAC) const; | ||||
|  | ||||
|     static int GetInfoByWMI(); | ||||
|  | ||||
|     static void GetInfoByEnumDisplayMonitors(); | ||||
|  | ||||
|     static int GetInfoByEnumDisplayDevices(); | ||||
|  | ||||
|     static int GetInfoByQueryDisplayConfig(); | ||||
|  | ||||
|     static int GetInfoByCfgmgr(); | ||||
|  | ||||
| private: | ||||
| }; | ||||
|   | ||||
| @@ -3,24 +3,25 @@ | ||||
|  | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
| #include <windows.h> | ||||
| #include <vector> | ||||
|  | ||||
| #include "Utils/SysInfoUtil.h" | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     SysInfoUtil util; | ||||
|     char mac[18]; | ||||
|  | ||||
|     // 测量函数调用的耗时 | ||||
|     auto start = chrono::high_resolution_clock::now(); | ||||
|     util.GetMacByGetAdaptersInfo(mac); | ||||
| 	auto start = chrono::high_resolution_clock::now(); | ||||
|     SysInfoUtil::GetInfoByEnumDisplayDevices(); | ||||
|     SysInfoUtil::GetInfoByEnumDisplayMonitors(); | ||||
|     SysInfoUtil::GetInfoByWMI(); | ||||
|     // SysInfoUtil::GetInfoByCfgmgr(); | ||||
|     SysInfoUtil::GetInfoByQueryDisplayConfig(); | ||||
|     auto end = chrono::high_resolution_clock::now(); | ||||
|     auto duration = chrono::duration_cast<chrono::milliseconds>(end - start); | ||||
|     cout << "Function call duration: " << duration.count() << " ms" << endl; | ||||
|  | ||||
|     // 输出日志信息 | ||||
|     cout << "MAC address: " << mac << endl; | ||||
|     wcout << "Function call duration: " << duration.count() << " ms" << endl; | ||||
| } | ||||
|  | ||||
| // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
|     <Keyword>Win32Proj</Keyword> | ||||
|     <ProjectGuid>{fc07175f-ec7a-4ce5-9f7f-976dc6aed04d}</ProjectGuid> | ||||
|     <RootNamespace>WinDevice</RootNamespace> | ||||
|     <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> | ||||
|     <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | ||||
| @@ -72,6 +72,7 @@ | ||||
|   <PropertyGroup Label="UserMacros" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <LinkIncremental>true</LinkIncremental> | ||||
|     <IncludePath>$(IncludePath)</IncludePath> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <LinkIncremental>false</LinkIncremental> | ||||
| @@ -93,6 +94,7 @@ | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>dxgi.lib;cfgmgr32.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|   | ||||
| @@ -18,5 +18,25 @@ | ||||
|     <ClCompile Include="WinDevice.cpp"> | ||||
|       <Filter>源文件</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="Audio\AudioManager.cpp"> | ||||
|       <Filter>源文件</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="Utils\SysInfoUtil.cpp"> | ||||
|       <Filter>源文件</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="Audio\AudioEnum.h"> | ||||
|       <Filter>头文件</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="Audio\AudioManager.h"> | ||||
|       <Filter>头文件</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="stdafx.h"> | ||||
|       <Filter>头文件</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="Utils\SysInfoUtil.h"> | ||||
|       <Filter>头文件</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
| @@ -1,4 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <PropertyGroup /> | ||||
|   <PropertyGroup> | ||||
|     <ShowAllFiles>true</ShowAllFiles> | ||||
|   </PropertyGroup> | ||||
| </Project> | ||||
		Reference in New Issue
	
	Block a user