pub use self::win::Win;
use dc::DeviceContext;
use windows::{
core::*,
Win32::{
Foundation::*, Graphics::Gdi::TEXTMETRICW, System::LibraryLoader::GetModuleHandleW,
UI::WindowsAndMessaging::*,
},
};
pub mod dc;
pub mod kbd;
pub mod mouse;
pub mod win;
pub mod win_create_args;
pub enum SendMessageParams {
Close,
}
#[derive(PartialEq)]
pub enum EventHandled {
Handled(LRESULT),
NotHandled,
}
#[derive(Debug)]
pub struct Event {
pub hwnd: HWND,
pub message: u32,
pub wparam: WPARAM,
pub lparam: LPARAM,
}
#[derive(PartialEq, Debug)]
pub enum SourceType {
Menu,
Accelerator,
Control,
}
#[derive(Debug)]
pub struct CommandEvent {
command: i32,
source_type: SourceType,
control_hwnd: Option<HWND>,
}
#[macro_export]
macro_rules! default_win_impl {
() => {
fn get_hwnd(&self) -> HWND {
self.base.hwnd
}
fn set_hwnd(&mut self, hwnd: HWND) {
self.base.hwnd = hwnd;
}
fn to_self_ptr(ptr: *mut ::core::ffi::c_void) -> *mut Self {
ptr as *mut Self
}
fn raw_ptr_isize(raw_ptr: *mut Self) -> isize {
raw_ptr as _
}
fn get_canary(&self) -> i32 {
self.base.canary
}
fn get_base(&mut self) -> &mut BaseWin {
&mut self.base
}
};
}
pub struct BaseWin {
pub hwnd: HWND,
pub canary: i32,
pub tm: TEXTMETRICW,
pub x: i32,
pub y: i32,
}
impl Default for BaseWin {
fn default() -> Self {
Self {
hwnd: HWND::default(),
canary: 99,
tm: TEXTMETRICW::default(),
x: 0,
y: 0,
}
}
}
impl BaseWin {
pub fn on_create(&mut self, _event: &Event) {
let dc = DeviceContext::get_dc(self.hwnd);
self.tm = dc.text_metrics();
}
pub fn on_resize(&mut self, x: i32, y: i32) -> EventHandled {
self.x = x;
self.y = y;
EventHandled::Handled(LRESULT(0))
}
}
struct WPModule {
hinst: HINSTANCE,
}
impl WPModule {
fn new() -> WPModule {
unsafe {
match GetModuleHandleW(None) {
Ok(hinst) => WPModule {
hinst: hinst.into(),
},
Err(error) => {
println!("error getting hinstance: {:?}", error);
WPModule {
hinst: HINSTANCE(0),
}
}
}
}
}
fn get_hinstance(&self) -> HINSTANCE {
self.hinst
}
}
pub struct WPApp<T: Win> {
module: WPModule,
pub main_win: T,
exit_code: WPARAM,
accel: Option<HACCEL>,
}
impl<T: Win> WPApp<T> {
pub fn new() -> Self {
let module = WPModule::new();
let main_win = T::new(module.hinst);
WPApp {
module: module,
main_win: main_win,
exit_code: WPARAM(0),
accel: None,
}
}
pub fn init(&mut self, title: PCWSTR) -> Result<()> {
self.main_win.create_window(title)?;
match self.load_accelerators() {
Ok(accel) => self.accel = Some(accel),
Err(_err) => println!("couldn't load accelerator"),
}
Ok(())
}
pub fn load_accelerators(&self) -> Result<HACCEL> {
unsafe { LoadAcceleratorsW(self.get_hinstance(), w!("AppAccel")) }
}
pub fn get_hinstance(&self) -> HINSTANCE {
self.module.get_hinstance()
}
pub fn exit_code(&self) -> WPARAM {
self.exit_code
}
pub fn get_message(msg: &mut MSG) -> bool {
unsafe { GetMessageW(msg, None, 0, 0).into() }
}
pub fn peek_message(msg: &mut MSG) -> bool {
unsafe { PeekMessageW(msg, None, 0, 0, PM_REMOVE).into() }
}
pub fn translate_accelerator(&self, accel: HACCEL, msg: MSG) -> bool {
let msg = &msg as *const _;
unsafe { TranslateAcceleratorW(self.main_win.get_hwnd(), accel, msg) > 0 }
}
pub fn translate_message(msg: &MSG) -> bool {
unsafe { TranslateMessage(msg).as_bool() }
}
pub fn dispatch_message(msg: &MSG) {
unsafe {
DispatchMessageW(msg);
}
}
pub fn run(&mut self) -> () {
self.main_win.show();
self.main_win.update();
let mut msg = MSG::default();
let mut peek = true;
while peek || Self::get_message(&mut msg) {
if peek {
if Self::peek_message(&mut msg) {
peek = self.main_win.do_idle();
continue;
}
if msg.message == WM_QUIT {
break;
}
}
let accel_message = match self.accel {
None => false,
Some(accel) => self.translate_accelerator(accel, msg),
};
if !accel_message {
Self::translate_message(&msg);
Self::dispatch_message(&msg);
}
}
self.exit_code = msg.wParam
}
}
pub fn load_icon(inst: HINSTANCE, name: PCWSTR) -> Result<HICON> {
match hword(name.0 as isize) {
0 => unsafe { LoadIconW(None, name) },
_ => unsafe { LoadIconW(inst, name) },
}
}
pub fn load_cursor(inst: Option<HINSTANCE>, name: PCWSTR) -> Result<HCURSOR> {
match inst {
None => unsafe { LoadCursorW(None, name) },
Some(inst) => unsafe { LoadCursorW(inst, name) },
}
}
fn get_utf16_vec(text: &str) -> Vec<u16> {
let mut text: Vec<u16> = text.encode_utf16().collect();
text.push(0);
text
}
pub fn lword(val: isize) -> i32 {
(val & 0xffff) as i32
}
pub fn hword(val: isize) -> i32 {
((val >> 16) & 0xffff) as i32
}
#[cfg(test)]
mod tests {
use super::*;
}