Skip to content

Instantly share code, notes, and snippets.

@duckcantcode
Created October 28, 2024 01:30
Show Gist options
  • Select an option

  • Save duckcantcode/3e66912adecd8702811dfba2de4bc2b9 to your computer and use it in GitHub Desktop.

Select an option

Save duckcantcode/3e66912adecd8702811dfba2de4bc2b9 to your computer and use it in GitHub Desktop.
Get all friendly monitor names (model number, brand) in Rust
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