use std::io::{self, Write}; use std::ptr; use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::System::Console::{ GetConsoleMode, ReadConsoleW, SetConsoleMode, GetStdHandle, STD_INPUT_HANDLE, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, }; fn main() -> io::Result<()> { unsafe { let h: HANDLE = GetStdHandle(STD_INPUT_HANDLE); if h == std::ptr::null_mut() || h == -1_i32 as HANDLE { return Err(io::Error::last_os_error()); } // save current mode let mut mode: u32 = 0; if GetConsoleMode(h, &mut mode) == 0 { return Err(io::Error::last_os_error()); } // disable line input and echo so input is available per-key and not echoed let new_mode = mode & !(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); if SetConsoleMode(h, new_mode) == 0 { return Err(io::Error::last_os_error()); } print!("Press keys (q to exit): "); io::stdout().flush()?; // ReadConsoleW reads UTF-16; we'll read one wchar at a time let mut buf: [u16; 1] = [0]; loop { let mut read = 0u32; if ReadConsoleW( h, buf.as_mut_ptr() as *mut _, 1, &mut read, ptr::null_mut(), ) == 0 { // restore mode on error before returning let _ = SetConsoleMode(h, mode); return Err(io::Error::last_os_error()); } let ch = std::char::from_u32(buf[0] as u32).unwrap_or('\u{FFFD}'); if ch == 'q' { break; } // q to exit // handle Enter (CR) so output is readable if ch == '\r' { println!(); } else { // show code point (no automatic console echo) print!("[{:?}]", ch); io::stdout().flush()?; } } // restore original console mode let _ = SetConsoleMode(h, mode); println!("\nexited"); } Ok(()) }