Returns (hwnd, physical_w, physical_h). Caller's `width`/`height` are *logical* — on a HiDPI monitor with scale 2.0 the window will appear logically the right size while its client area is scaled-up physical pixels for the renderer to fill.
(width: f64, height: f64, title: &str)
| 210 | /// will appear logically the right size while its client area is |
| 211 | /// scaled-up physical pixels for the renderer to fill. |
| 212 | pub fn create_window(width: f64, height: f64, title: &str) -> (HWND, u32, u32) { |
| 213 | unsafe { |
| 214 | // Per-Monitor-Aware-V2: the window's DPI tracks the monitor |
| 215 | // it's currently on, and Windows fires WM_DPICHANGED when |
| 216 | // it moves between monitors of different DPI. Without this |
| 217 | // call, Win32 silently virtualises us to 96 DPI on HiDPI |
| 218 | // displays — a 4K monitor would render at ~2560×1440. |
| 219 | // Safe to call early; ignored on pre-Win10 1703. |
| 220 | let _ = SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); |
| 221 | |
| 222 | let hmodule = GetModuleHandleW(None).unwrap(); |
| 223 | let hinstance: HINSTANCE = hmodule.into(); |
| 224 | let class_name = w!("BloomWindowClass"); |
| 225 | |
| 226 | let wc = WNDCLASSEXW { |
| 227 | cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32, |
| 228 | style: CS_HREDRAW | CS_VREDRAW, |
| 229 | lpfnWndProc: Some(wndproc), |
| 230 | hInstance: hinstance, |
| 231 | lpszClassName: class_name, |
| 232 | hCursor: LoadCursorW(None, IDC_ARROW).unwrap(), |
| 233 | ..Default::default() |
| 234 | }; |
| 235 | RegisterClassExW(&wc); |
| 236 | |
| 237 | let title_wide: Vec<u16> = title.encode_utf16().chain(std::iter::once(0)).collect(); |
| 238 | |
| 239 | // Initial window size in physical pixels. We don't have a |
| 240 | // window handle yet, so use the system DPI — close enough, |
| 241 | // and WM_DPICHANGED will resize on the first move if the |
| 242 | // user lands on a different-DPI monitor. |
| 243 | let system_dpi = GetDpiForSystem().max(96); |
| 244 | let scale = system_dpi as f64 / 96.0; |
| 245 | let phys_w = (width * scale).round() as i32; |
| 246 | let phys_h = (height * scale).round() as i32; |
| 247 | |
| 248 | let hwnd = CreateWindowExW( |
| 249 | WINDOW_EX_STYLE::default(), |
| 250 | class_name, |
| 251 | PCWSTR(title_wide.as_ptr()), |
| 252 | WS_OVERLAPPEDWINDOW | WS_VISIBLE, |
| 253 | CW_USEDEFAULT, CW_USEDEFAULT, |
| 254 | phys_w, phys_h, |
| 255 | None, None, Some(&hinstance), None, |
| 256 | ).unwrap(); |
| 257 | |
| 258 | ShowWindow(hwnd, SW_SHOW); |
| 259 | HWND_GLOBAL = Some(hwnd); |
| 260 | |
| 261 | // After the window exists, query the actual client-area |
| 262 | // size. Includes whatever DWM trimmed for borders and |
| 263 | // reflects this monitor's DPI rather than the system one. |
| 264 | let mut rect = RECT::default(); |
| 265 | let _ = GetClientRect(hwnd, &mut rect); |
| 266 | let actual_w = (rect.right - rect.left).max(1) as u32; |
| 267 | let actual_h = (rect.bottom - rect.top).max(1) as u32; |
| 268 | (hwnd, actual_w, actual_h) |
| 269 | } |
no test coverage detected