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}