native_windows_gui2/win32/
monitor.rs

1use crate::ControlHandle;
2use std::mem;
3use winapi::shared::windef::HWND;
4use winapi::um::winuser::{
5    GetMonitorInfoW, GetSystemMetrics, MONITOR_DEFAULTTONEAREST, MONITORINFO, MonitorFromWindow,
6    SM_CXSCREEN, SM_CXVIRTUALSCREEN, SM_CYSCREEN, SM_CYVIRTUALSCREEN,
7};
8
9/**
10    Expose basic properties of the monitor(s) on the system and the virtual screen.
11
12    This object cannot be instanced. The methods should be used this way:
13
14    ```rust
15    // Creating and centering a window in the main monitor
16
17    use native_windows_gui2 as nwg;
18
19    fn create_window(width: i32, height: i32) -> nwg::Window {
20        let [total_width, total_height] = [nwg::Monitor::width(), nwg::Monitor::height()];
21        let mut window = nwg::Window::default();
22
23        let x = (total_width-width)/2;
24        let y = (total_height-height)/2;
25
26        nwg::Window::builder()
27            .size((width, height))
28            .position((x, y))
29            .build(&mut window)
30            .unwrap();
31
32        window
33    }
34
35    ```
36*/
37pub struct Monitor;
38
39impl Monitor {
40    fn monitor_info_from_window(handle: HWND) -> MONITORINFO {
41        unsafe {
42            let m = MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST);
43
44            let mut info: MONITORINFO = mem::zeroed();
45            info.cbSize = mem::size_of::<MONITORINFO>() as _;
46            GetMonitorInfoW(m, &mut info);
47
48            info
49        }
50    }
51
52    /// Returns the width in pixel of the monitor that has the largest area of intersection with the bounding rectangle of a specified window
53    /// If the window does not intersect any display monitor, returns the nearest monitor width
54    /// Panics if `window` is not a window like control.
55    pub fn width_from_window<H: Into<ControlHandle>>(window: H) -> i32 {
56        let handle = window
57            .into()
58            .hwnd()
59            .expect("Window to be a window-like control");
60        let info = Self::monitor_info_from_window(handle);
61        (info.rcMonitor.right - info.rcMonitor.left) as _
62    }
63
64    /// Returns the height in pixel of the monitor that has the largest area of intersection with the bounding rectangle of a specified window
65    /// If the window does not intersect any display monitor, returns the nearest monitor height
66    /// Panics if `window` is not a window like control.
67    pub fn height_from_window<H: Into<ControlHandle>>(window: H) -> i32 {
68        let handle = window
69            .into()
70            .hwnd()
71            .expect("Window to be a window-like control");
72        let info = Self::monitor_info_from_window(handle);
73        (info.rcMonitor.bottom - info.rcMonitor.top) as _
74    }
75
76    /// Returns a [left, top, right, bottom] rectangle that specifies the display monitor rectangle, expressed in virtual-screen coordinates.
77    /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.
78    /// Panics if `window` is not a window like control.
79    pub fn monitor_rect_from_window<H: Into<ControlHandle>>(window: H) -> [i32; 4] {
80        let handle = window
81            .into()
82            .hwnd()
83            .expect("Window to be a window-like control");
84        let info = Self::monitor_info_from_window(handle);
85        let m = info.rcMonitor;
86
87        [m.left, m.top, m.right, m.bottom]
88    }
89
90    /// Returns the primary monitor width in pixel
91    /// Use `Monitor::virtual_width` to get the dimensions of the virtual screen
92    pub fn width() -> i32 {
93        unsafe { GetSystemMetrics(SM_CXSCREEN) as _ }
94    }
95
96    /// Returns the primary monitor height in pixel
97    /// Use `Monitor::virtual_height` to get the dimensions of the virtual screen
98    pub fn height() -> i32 {
99        unsafe { GetSystemMetrics(SM_CYSCREEN) as _ }
100    }
101
102    /// Returns the primary monitor width in pixel
103    /// Use `Monitor::width` to get the dimensions of the virtual screen
104    pub fn virtual_width() -> i32 {
105        unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) as _ }
106    }
107
108    /// Returns the primary monitor height in pixel
109    /// Use `Monitor::height` to get the dimensions of the virtual screen
110    pub fn virtual_height() -> i32 {
111        unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) as _ }
112    }
113}