#![windows_subsystem = "windows"] | |
extern crate winapi; | |
extern crate user32; | |
extern crate kernel32; | |
use std::ffi::OsStr; | |
use std::os::windows::ffi::OsStrExt; | |
use std::iter::once; | |
use std::mem; | |
use std::ptr::null_mut; | |
use std::io::Error; | |
use self::user32::{ | |
DefWindowProcW, | |
RegisterClassW, | |
CreateWindowExW, | |
TranslateMessage, | |
DispatchMessageW, | |
GetMessageW, | |
}; | |
use self::winapi::HWND; | |
use self::kernel32::GetModuleHandleW; | |
use self::winapi::winuser::{ | |
MSG, | |
WNDCLASSW, | |
CS_OWNDC, | |
CS_HREDRAW, | |
CS_VREDRAW, | |
CW_USEDEFAULT, | |
WS_OVERLAPPEDWINDOW, | |
WS_VISIBLE, | |
}; | |
fn win32_string( value : &str ) -> Vec<u16> { | |
OsStr::new( value ).encode_wide().chain( once( 0 ) ).collect() | |
} | |
struct Window { | |
handle : HWND, | |
} | |
fn create_window( name : &str, title : &str ) -> Result<Window, Error> { | |
let name = win32_string( name ); | |
let title = win32_string( title ); | |
unsafe { | |
let hinstance = GetModuleHandleW( null_mut() ); | |
let wnd_class = WNDCLASSW { | |
style : CS_OWNDC | CS_HREDRAW | CS_VREDRAW, | |
lpfnWndProc : Some( DefWindowProcW ), | |
hInstance : hinstance, | |
lpszClassName : name.as_ptr(), | |
cbClsExtra : 0, | |
cbWndExtra : 0, | |
hIcon: null_mut(), | |
hCursor: null_mut(), | |
hbrBackground: null_mut(), | |
lpszMenuName: null_mut(), | |
}; | |
RegisterClassW( &wnd_class ); | |
let handle = CreateWindowExW( | |
0, | |
name.as_ptr(), | |
title.as_ptr(), | |
WS_OVERLAPPEDWINDOW | WS_VISIBLE, | |
CW_USEDEFAULT, | |
CW_USEDEFAULT, | |
CW_USEDEFAULT, | |
CW_USEDEFAULT, | |
null_mut(), | |
null_mut(), | |
hinstance, | |
null_mut() ); | |
if handle.is_null() { | |
Err( Error::last_os_error() ) | |
} else { | |
Ok( Window { handle } ) | |
} | |
} | |
} | |
fn handle_message( window : &mut Window ) -> bool { | |
unsafe { | |
let mut message : MSG = mem::uninitialized(); | |
if GetMessageW( &mut message as *mut MSG, window.handle, 0, 0 ) > 0 { | |
TranslateMessage( &message as *const MSG ); | |
DispatchMessageW( &message as *const MSG ); | |
true | |
} else { | |
false | |
} | |
} | |
} | |
fn main() { | |
let mut window = create_window( "my_window", "Hello Windows" ).unwrap(); | |
loop { | |
if !handle_message( &mut window ) { | |
break; | |
} | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
Hi. First of all apologies for the late reply but for some reason I haven't seen this update at all! Unfortunately I am not using windows for my day-to-day work anymore so I won't be able to update my blog post with all the changes that have been made since I last used the |
This comment has been minimized.
This comment has been minimized.
Thanks TheSatoshiChiba for the tutorial and lightern for the update. I just wanted to mention that modules like Here is mine:
|
This comment has been minimized.
This comment has been minimized.
Thanks to everyone who has commented so far. I would suggest a tweak to handle_message to eliminate the deprecated call to mem::uninitialized() by replacing it with mem::MaybeUninit. https://doc.rust-lang.org/std/mem/union.MaybeUninit.html
|
This comment has been minimized.
This comment has been minimized.
+1 thanks for all the contributors :) |
This comment has been minimized.
First of all, thank you so much for your your text and gist! I've found this super helpful while trying to learn Rust and windows api at the same time. However I noticed that your guide was a bit outdated since winapi has been merged with user32 and kernel32 and I was thinking it would be great, if you could update your guide for others, since I bet there are many people like me wrestling with this. Also I would love to see #2 part of this guide with tips how to implement menu and some kind of input with button :)
Anyway, here's my sketch on the up to date version (please don't mind the additional comments, those were for me to make things more clear):