Created
September 1, 2018 05:54
-
-
Save rokit/b97a7199103c4be31706b4f11e33213f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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