Created
October 28, 2024 01:30
-
-
Save duckcantcode/3e66912adecd8702811dfba2de4bc2b9 to your computer and use it in GitHub Desktop.
Get all friendly monitor names (model number, brand) in Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use windows::Win32::Devices::Display::DISPLAYCONFIG_PATH_INFO; | |
| use windows::Win32::{ | |
| Devices::Display::{ | |
| DisplayConfigGetDeviceInfo, GetDisplayConfigBufferSizes, QueryDisplayConfig, | |
| DISPLAYCONFIG_ADAPTER_NAME, DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME, | |
| DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME, DISPLAYCONFIG_MODE_INFO, | |
| DISPLAYCONFIG_TARGET_DEVICE_NAME, QDC_ONLY_ACTIVE_PATHS, | |
| QDC_VIRTUAL_MODE_AWARE, | |
| }, | |
| Foundation::{ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS, WIN32_ERROR}, | |
| }; | |
| // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig#examples | |
| pub unsafe fn get_monitor_names() -> Option<Vec<String>> { | |
| let mut names = vec![]; | |
| let mut paths: Vec<DISPLAYCONFIG_PATH_INFO> = vec![]; | |
| let mut modes: Vec<DISPLAYCONFIG_MODE_INFO> = vec![]; | |
| let flags = QDC_ONLY_ACTIVE_PATHS | QDC_VIRTUAL_MODE_AWARE; | |
| let mut result; | |
| loop { | |
| let mut path_count: u32 = 0; | |
| let mut mode_count: u32 = 0; | |
| result = GetDisplayConfigBufferSizes(flags, &mut path_count, &mut mode_count); | |
| if result != ERROR_SUCCESS { | |
| return None; | |
| } | |
| paths.resize( | |
| path_count.try_into().unwrap(), | |
| DISPLAYCONFIG_PATH_INFO::default(), | |
| ); | |
| modes.resize( | |
| mode_count.try_into().unwrap(), | |
| DISPLAYCONFIG_MODE_INFO::default(), | |
| ); | |
| result = QueryDisplayConfig( | |
| flags, | |
| &mut path_count, | |
| paths.as_mut_ptr(), | |
| &mut mode_count, | |
| modes.as_mut_ptr(), | |
| None, | |
| ); | |
| paths.resize( | |
| path_count.try_into().unwrap(), | |
| DISPLAYCONFIG_PATH_INFO::default(), | |
| ); | |
| modes.resize( | |
| mode_count.try_into().unwrap(), | |
| DISPLAYCONFIG_MODE_INFO::default(), | |
| ); | |
| if result != ERROR_INSUFFICIENT_BUFFER { | |
| break; | |
| } | |
| } | |
| if result != ERROR_SUCCESS { | |
| return None; | |
| } | |
| for path in paths { | |
| let mut target_name = DISPLAYCONFIG_TARGET_DEVICE_NAME::default(); | |
| target_name.header.adapterId = path.targetInfo.adapterId; | |
| target_name.header.id = path.targetInfo.id; | |
| target_name.header.r#type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; | |
| target_name.header.size = core::mem::size_of::<DISPLAYCONFIG_TARGET_DEVICE_NAME>() as u32; | |
| result = WIN32_ERROR( | |
| DisplayConfigGetDeviceInfo(&mut target_name.header) | |
| .try_into() | |
| .unwrap(), | |
| ); | |
| if result.is_err() { | |
| return None; | |
| } | |
| let mut adapter_name = DISPLAYCONFIG_ADAPTER_NAME::default(); | |
| adapter_name.header.adapterId = path.targetInfo.adapterId; | |
| adapter_name.header.r#type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME; | |
| adapter_name.header.size = core::mem::size_of::<DISPLAYCONFIG_ADAPTER_NAME>() as u32; | |
| result = WIN32_ERROR( | |
| DisplayConfigGetDeviceInfo(&mut adapter_name.header) | |
| .try_into() | |
| .unwrap(), | |
| ); | |
| if result.is_err() { | |
| return None; | |
| } | |
| let dstr = widestring::U16String::from_vec(target_name.monitorFriendlyDeviceName) | |
| .to_string_lossy(); | |
| names.push(dstr.trim_end_matches("\0").to_string()); | |
| } | |
| Some(names) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment