rust_minifb/src/windows.rs

166 lines
5.2 KiB
Rust
Raw Normal View History

2015-11-28 07:25:50 +11:00
extern crate user32;
extern crate kernel32;
extern crate winapi;
2015-11-28 09:42:28 +11:00
extern crate gdi32;
2015-11-28 07:25:50 +11:00
use std::ffi::CString;
use std::ptr;
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;
use std::mem;
use self::winapi::windef::HWND;
use self::winapi::winuser::WS_OVERLAPPEDWINDOW;
use self::winapi::winuser::WNDCLASSW;
2015-11-28 09:42:28 +11:00
use self::winapi::wingdi::BITMAPINFOHEADER;
use self::winapi::wingdi::RGBQUAD;
2015-11-28 07:25:50 +11:00
static mut CLOSE_APP: bool = false;
2015-11-28 09:42:28 +11:00
// Wrap this so we can have a proper numbef of bmiColors to write in
#[repr(C)]
struct BitmapInfo {
pub bmi_header: BITMAPINFOHEADER,
pub bmi_colors: [RGBQUAD; 3],
}
2015-11-28 07:25:50 +11:00
unsafe extern "system" fn wnd_proc(window: winapi::HWND, msg: winapi::UINT,
2015-11-28 05:14:24 +11:00
wparam: winapi::WPARAM, lparam: winapi::LPARAM)
-> winapi::LRESULT
{
match msg {
2015-11-28 07:25:50 +11:00
winapi::winuser::WM_KEYDOWN => {
if (wparam & 0xff) == 27 {
CLOSE_APP = true;
}
2015-11-28 05:14:24 +11:00
}
2015-11-28 07:25:50 +11:00
2015-11-28 09:42:28 +11:00
winapi::winuser::WM_PAINT => {
let mut rect: winapi::RECT = mem::uninitialized();
let buffer = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA);
user32::GetClientRect(window, &mut rect);
let mut bitmap_info: BitmapInfo = mem::zeroed();
let width = rect.right - rect.left;
let height = rect.bottom - rect.top;
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
bitmap_info.bmi_header.biPlanes = 1;
bitmap_info.bmi_header.biBitCount = 32;
bitmap_info.bmi_header.biCompression = winapi::wingdi::BI_BITFIELDS;
bitmap_info.bmi_header.biWidth = width;
bitmap_info.bmi_header.biHeight = -height;
bitmap_info.bmi_colors[0].rgbRed = 0xff;
bitmap_info.bmi_colors[1].rgbGreen = 0xff;
bitmap_info.bmi_colors[2].rgbBlue = 0xff;
let dc = user32::GetDC(window);
gdi32::StretchDIBits(dc, 0, 0, width, height, 0, 0, width, height,
mem::transmute(buffer),
mem::transmute(&bitmap_info),
winapi::wingdi::DIB_RGB_COLORS,
winapi::wingdi::SRCCOPY);
user32::ValidateRect(window, ptr::null_mut());
user32::ReleaseDC(window, dc);
}
2015-11-28 07:25:50 +11:00
_ => (),
2015-11-28 05:14:24 +11:00
}
2015-11-28 07:25:50 +11:00
return user32::DefWindowProcW(window, msg, wparam, lparam);
2015-11-28 05:14:24 +11:00
}
2015-11-28 07:25:50 +11:00
pub enum MinifbError {
UnableToCreateWindow,
}
2015-11-28 05:14:24 +11:00
2015-11-28 07:25:50 +11:00
fn to_wstring(str : &str) -> *const u16 {
let v : Vec<u16> = OsStr::new(str).encode_wide(). chain(Some(0).into_iter()).collect();
v.as_ptr()
2015-11-28 05:14:24 +11:00
}
2015-11-28 07:25:50 +11:00
pub struct Minifb {
window: HWND,
}
2015-11-28 05:14:24 +11:00
2015-11-28 07:25:50 +11:00
impl Minifb {
fn open_window(name: &str, width: usize, height: usize) -> HWND {
unsafe {
let class_name = to_wstring("minifb_window");
let s = CString::new(name).unwrap();
let class = WNDCLASSW {
style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
lpfnWndProc: Some(wnd_proc),
cbClsExtra: 0,
cbWndExtra: 0,
hInstance: kernel32::GetModuleHandleA(ptr::null()),
hIcon: ptr::null_mut(),
hCursor: ptr::null_mut(),
hbrBackground: ptr::null_mut(),
lpszMenuName: ptr::null(),
lpszClassName: class_name,
};
user32::RegisterClassW(&class);
let mut rect = winapi::RECT {
left: 0, right: width as winapi::LONG,
top: 0, bottom: height as winapi::LONG,
};
user32::AdjustWindowRect(&mut rect, winapi::WS_POPUP | winapi::WS_SYSMENU | winapi::WS_CAPTION, 0);
rect.right -= rect.left;
rect.bottom -= rect.top;
let handle = user32::CreateWindowExA(0,
"minifb_window".as_ptr() as *mut _, s.as_ptr(),
winapi::WS_OVERLAPPEDWINDOW & !winapi::WS_MAXIMIZEBOX & !winapi::WS_THICKFRAME,
winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
rect.right, rect.bottom,
ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut());
if !handle.is_null() {
user32::ShowWindow(handle, winapi::SW_NORMAL);
}
return handle;
}
}
2015-11-28 05:14:24 +11:00
2015-11-28 07:25:50 +11:00
pub fn new(name: &str, width: usize, height: usize) -> Option<Minifb> {
let handle = Minifb::open_window(name, width, height);
2015-11-28 05:14:24 +11:00
2015-11-28 07:25:50 +11:00
match handle.is_null() {
true => None,
false => Some(Minifb { window : handle }),
}
2015-11-28 05:14:24 +11:00
}
2015-11-28 09:42:28 +11:00
pub fn update(&mut self, buffer: &[u32]) -> bool {
2015-11-28 07:25:50 +11:00
unsafe {
let mut msg = mem::uninitialized();
2015-11-28 09:42:28 +11:00
user32::SetWindowLongPtrW(self.window, winapi::winuser::GWLP_USERDATA, buffer.as_ptr() as i64);
2015-11-28 07:25:50 +11:00
user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE);
while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) != 0 {
user32::TranslateMessage(&mut msg);
user32::DispatchMessageW(&mut msg);
}
}
unsafe {
return !CLOSE_APP;
}
}
}
2015-11-28 07:25:50 +11:00