Windows中如何检测显示器是否已断开连接(C++开发场景)
解决方案
你之前的方法无法正确检测断开状态的核心原因是:DISPLAY_DEVICE_ACTIVE标记仅表示设备已被系统识别并加载驱动,即使你在显示设置中“断开”显示器,设备本身仍处于激活状态,因此这个标记无法区分显示器当前是否在输出画面。
要准确检测系统显示设置中处于断开状态的显示器,应该使用QueryDisplayConfig API获取当前活跃的显示路径,再结合EnumDisplayDevices枚举的所有设备进行对比,不在活跃路径中的设备就是断开状态的。
实现代码
1. 获取活跃显示器列表
#include <Windows.h> #include <vector> #include <string> #include <iostream> #pragma comment(lib, "user32.lib") // 获取当前活跃(正在显示)的显示器设备路径 std::vector<std::wstring> GetActiveMonitorDeviceNames() { std::vector<std::wstring> activeDevices; UINT32 pathCount = 0; UINT32 modeCount = 0; // 先查询所需缓冲区大小 if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount) != ERROR_SUCCESS) { return activeDevices; } std::vector<DISPLAYCONFIG_PATH_INFO> paths(pathCount); std::vector<DISPLAYCONFIG_MODE_INFO> modes(modeCount); if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.data(), &modeCount, modes.data(), nullptr) != ERROR_SUCCESS) { return activeDevices; } for (const auto& path : paths) { DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; targetName.header.size = sizeof(targetName); targetName.header.adapterId = path.targetInfo.adapterId; targetName.header.id = path.targetInfo.id; if (DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS) { activeDevices.push_back(targetName.monitorDevicePath); } } return activeDevices; }
2. 完整的显示器信息枚举(含断开状态检测)
struct MonitorInfo { std::wstring name; // 设备名称(如\\.\DISPLAY1) std::wstring deviceString; // 显示器型号名称 int width; // 当前分辨率宽度 int height; // 当前分辨率高度 int refreshRate; // 当前刷新率 bool isActive; // 是否处于活跃(连接显示)状态 }; std::vector<MonitorInfo> GetMonitorInfo() { std::vector<MonitorInfo> monitors; auto activeDevices = GetActiveMonitorDeviceNames(); DISPLAY_DEVICE displayDevice = {}; displayDevice.cb = sizeof(DISPLAY_DEVICE); int deviceIndex = 0; while (EnumDisplayDevicesW(NULL, deviceIndex, &displayDevice, 0)) { MonitorInfo info; info.name = displayDevice.DeviceName; info.deviceString = displayDevice.DeviceString; info.isActive = false; // 对比活跃列表,标记当前设备是否在显示中 for (const auto& activeDev : activeDevices) { if (info.name == activeDev) { info.isActive = true; break; } } DEVMODEW devMode = {}; devMode.dmSize = sizeof(DEVMODEW); devMode.dmDriverExtra = 0; if (EnumDisplaySettingsExW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode, 0)) { info.width = devMode.dmPelsWidth; info.height = devMode.dmPelsHeight; info.refreshRate = devMode.dmDisplayFrequency; } else { // 无法获取当前设置,说明显示器未激活 info.width = 0; info.height = 0; info.refreshRate = 0; } monitors.push_back(info); deviceIndex++; } return monitors; } int main() { std::vector<MonitorInfo> monitors = GetMonitorInfo(); for (const auto& monitor : monitors) { std::wcout << L"Monitor Name: " << monitor.name << std::endl; std::wcout << L"Monitor String: " << monitor.deviceString << std::endl; std::wcout << L"Resolution: " << monitor.width << L"x" << monitor.height << std::endl; std::wcout << L"Refresh Rate: " << monitor.refreshRate << L" Hz" << std::endl; std::wcout << L"Is Connected: " << (monitor.isActive ? L"Yes" : L"No") << std::endl; std::wcout << std::endl; } return 0; }
原理说明
QueryDisplayConfig配合QDC_ONLY_ACTIVE_PATHS参数,仅返回当前正在输出画面的显示路径,对应系统显示设置中“连接”状态的显示器。- 通过对比
EnumDisplayDevices枚举的所有设备,就能筛选出不在活跃路径中的、处于“断开”状态的显示器。 - 该方法对物理显示器和虚拟显示器均有效。
内容的提问来源于stack exchange,提问作者forDream
相关产品推荐
相关产品推荐

