Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
// Let's put this so that it won't open console
#![windows_subsystem = "windows"]
extern crate winapi;
// https://docs.rs/winapi/*/x86_64-pc-windows-msvc/winapi/um/libloaderapi/index.html?search=winuser
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 winapi::shared::windef::{
HWND,
RECT,
HDC,
HBRUSH,
};
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::um::winuser::{
DefWindowProcW,
RegisterClassW,
CreateWindowExW,
TranslateMessage,
DispatchMessageW,
GetMessageW,
};
use winapi::um::winuser::{
MSG,
WNDCLASSW,
CS_OWNDC,
CS_HREDRAW,
CS_VREDRAW,
CW_USEDEFAULT,
WS_OVERLAPPEDWINDOW,
WS_VISIBLE,
PAINTSTRUCT,
BeginPaint,
EndPaint,
COLOR_WINDOW,
FillRect,
WM_PAINT,
};
use winapi::shared::minwindef::{
BOOL,
BYTE,
UINT,
WPARAM,
LPARAM,
LRESULT
};
use winapi::um::winnt::LONG;
// ----------------------------------------------------
// We have to encode text to wide format for Windows
fn win32_string( value : &str ) -> Vec<u16> {
OsStr::new( value ).encode_wide().chain( once( 0 ) ).collect()
}
// Window struct
struct Window {
handle : HWND,
}
// Create window function
fn create_window( name : &str, title : &str ) -> Result<Window, Error> {
let name = win32_string( name );
let title = win32_string( title );
unsafe {
// Create handle instance that will call GetModuleHandleW, which grabs the instance handle of WNDCLASSW (check third parameter)
let hinstance = GetModuleHandleW( null_mut() );
// Create "class" for window, using WNDCLASSW struct (different from Window our struct)
let wnd_class = WNDCLASSW {
style : CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
// The callback function for any window event that can occur in our window!!!
// Here you could react to events like WM_SIZE or WM_QUIT.
lpfnWndProc : Some( callback ),
// The instance handle for our application which we can retrieve by calling GetModuleHandleW.
hInstance : hinstance,
// Our class name which needs to be a UTF-16 string (defined earlier before unsafe).
// as_ptr() (Rust's own function) returns a raw pointer to the slice's buffer
lpszClassName : name.as_ptr(),
cbClsExtra : 0,
cbWndExtra : 0,
hIcon: null_mut(),
hCursor: null_mut(),
hbrBackground: null_mut(),
lpszMenuName: null_mut(),
};
// We have to register this class for Windows to use
RegisterClassW( &wnd_class );
// More info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
// Create a window based on registered class
let handle = CreateWindowExW(
0, // dwExStyle
name.as_ptr(), // lpClassName, name of the class that we want to use for this window, which will be the same that we have registered before.
title.as_ptr(), // lpWindowName
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // dwStyle
CW_USEDEFAULT, // Int x
CW_USEDEFAULT, // Int y
CW_USEDEFAULT, // Int nWidth
CW_USEDEFAULT, // Int nHeight
null_mut(), // hWndParent
null_mut(), // hMenu
hinstance, // hInstance
null_mut() ); // lpParam
if handle.is_null() {
Err( Error::last_os_error() )
} else {
Ok( Window { handle } )
}
}
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx
unsafe extern "system" fn callback(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
match msg {
WM_PAINT => {
let mut ps = PAINTSTRUCT {
hdc: null_mut(),
fErase: 0 as BOOL,
rcPaint: RECT {
left: 0 as LONG, top: 0 as LONG,
right: 0 as LONG, bottom: 0 as LONG
},
fRestore: 0 as BOOL,
fIncUpdate: 0 as BOOL,
rgbReserved: [0 as BYTE; 32],
};
let mut hdc: HDC = BeginPaint(hwnd, &mut ps);
// colors: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getsyscolor
FillRect(hdc, &ps.rcPaint, COLOR_WINDOW as HBRUSH);
EndPaint(hwnd, &mut ps);
},
_ => {}
}
DefWindowProcW(hwnd, msg, wparam, lparam)
}
// Create message handling function with which to link to hook window to Windows messaging system
// More info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927(v=vs.85).aspx
fn handle_message( window : &mut Window ) -> bool {
unsafe {
let mut msg : MSG = mem::uninitialized();
// Get message from message queue with GetMessageW
if GetMessageW( &mut msg as *mut MSG, window.handle, 0, 0 ) > 0 {
TranslateMessage( &msg as *const MSG ); // Translate message into something meaningful with TranslateMessage
DispatchMessageW( &msg as *const MSG ); // Dispatch message with DispatchMessageW. This sends the message to our callback function above.
true
} else {
false
}
}
}
fn main() {
let mut window = create_window( "my_window", "Window Title" ).unwrap();
loop {
if !handle_message( &mut window ) {
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment