From e7c8a9780d3ac83bed463b9e28573f8ed884cbf7 Mon Sep 17 00:00:00 2001 From: Mirko Covizzi Date: Mon, 25 May 2020 21:35:03 +0200 Subject: [PATCH] Add Windows initial code --- .gitignore | 2 + Cargo.toml | 4 ++ examples/windows_demo.rs | 21 ++++++++++ src/lib.rs | 8 +++- src/win/mod.rs | 3 ++ src/win/window.rs | 83 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 examples/windows_demo.rs create mode 100644 src/win/mod.rs create mode 100644 src/win/window.rs diff --git a/.gitignore b/.gitignore index 96ef6c0..15baff9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /target Cargo.lock +.idea +*.iml diff --git a/Cargo.toml b/Cargo.toml index 8d79041..82e599f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +winapi = { version = "0.3.8", features = ["libloaderapi", "winuser", "windef", "minwindef"] } + +[[example]] +name = "windows_demo" \ No newline at end of file diff --git a/examples/windows_demo.rs b/examples/windows_demo.rs new file mode 100644 index 0000000..7c57ca5 --- /dev/null +++ b/examples/windows_demo.rs @@ -0,0 +1,21 @@ +use std::ptr::null_mut; + +use baseview::{WindowOpenOptions, create_window, handle_msg}; +use baseview::Parent; + +fn main() { + let window = WindowOpenOptions { + title: "Baseview", + width: 800, + height: 400, + parent: Parent::None + }; + + create_window(window); + + loop { + if !handle_msg(null_mut()) { + break; + } + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index e3fafdb..4a875d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,13 @@ +mod win; + +pub use win::*; + use std::ffi::c_void; pub enum Parent { None, AsIfParented, - WithParent(*mut c_void) + WithParent(*mut c_void), } pub struct WindowOpenOptions<'a> { @@ -12,5 +16,5 @@ pub struct WindowOpenOptions<'a> { pub width: usize, pub height: usize, - pub parent: Parent + pub parent: Parent, } diff --git a/src/win/mod.rs b/src/win/mod.rs new file mode 100644 index 0000000..b0fcdd9 --- /dev/null +++ b/src/win/mod.rs @@ -0,0 +1,3 @@ +mod window; + +pub use window::*; diff --git a/src/win/window.rs b/src/win/window.rs new file mode 100644 index 0000000..5c460cc --- /dev/null +++ b/src/win/window.rs @@ -0,0 +1,83 @@ +extern crate winapi; + +use self::winapi::_core::mem::MaybeUninit; +use self::winapi::shared::minwindef::{LPARAM, LPVOID, LRESULT, UINT, WPARAM}; +use self::winapi::shared::windef::{HBRUSH, HICON, HMENU, HWND}; +use self::winapi::um::libloaderapi::GetModuleHandleA; +use self::winapi::um::winuser::{ + CreateWindowExA, DefWindowProcA, DispatchMessageA, PeekMessageA, PostQuitMessage, + RegisterClassA, TranslateMessage, CS_HREDRAW, CS_OWNDC, CS_VREDRAW, CW_USEDEFAULT, MSG, + PM_REMOVE, WM_DESTROY, WM_QUIT, WNDCLASSA, WS_OVERLAPPEDWINDOW, WS_VISIBLE, +}; + +use crate::WindowOpenOptions; + +pub fn handle_msg(_window: HWND) -> bool { + unsafe { + let mut msg: MSG = MaybeUninit::uninit().assume_init(); + loop { + if PeekMessageA(&mut msg, 0 as HWND, 0, 0, PM_REMOVE) == 0 { + return true; + } + if msg.message == WM_QUIT { + return false; + } + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } +} + +pub unsafe extern "system" fn wnd_proc( + hwnd: HWND, + msg: UINT, + w_param: WPARAM, + l_param: LPARAM, +) -> LRESULT { + match msg { + WM_DESTROY => { + PostQuitMessage(0); + } + _ => { + return DefWindowProcA(hwnd, msg, w_param, l_param); + } + } + return 0; +} + +pub fn create_window(w: WindowOpenOptions) { + unsafe { + let hinstance = GetModuleHandleA(0 as *const i8); + let wnd_class = WNDCLASSA { + // todo: for OpenGL, will use it later + style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW, + lpfnWndProc: Some(wnd_proc), + hInstance: hinstance, + lpszClassName: "BaseviewClass\0".as_ptr() as *const i8, + cbClsExtra: 0, + cbWndExtra: 0, + hIcon: 0 as HICON, + hCursor: 0 as HICON, + hbrBackground: 0 as HBRUSH, + lpszMenuName: 0 as *const i8, + }; + RegisterClassA(&wnd_class); + + let _hwnd = CreateWindowExA( + 0, + "BaseviewClass\0".as_ptr() as *const i8, + "Baseview\0".as_ptr() as *const i8, + // todo: fine for now, will have to change with a parent + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + // todo: check if usize fits into i32 + w.width as i32, + w.height as i32, + 0 as HWND, + 0 as HMENU, + hinstance, + 0 as LPVOID, + ); + } +}