use super::{
dc::DeviceContext, hword, kbd::KbdEvent, load_icon, lword, mouse::MouseEvent,
win_create_args::WinCreateArgs, BaseWin, CommandEvent, Event, EventHandled, SendMessageParams,
SourceType,
};
use std::mem;
use windows::{
core::*,
Win32::{Foundation::*, Graphics::Gdi::*, UI::WindowsAndMessaging::*},
};
pub trait Win {
fn new(inst: HINSTANCE) -> Self;
fn get_hwnd(&self) -> HWND;
fn set_hwnd(&mut self, hwnd: HWND);
fn get_canary(&self) -> i32 {
10
}
fn get_base(&mut self) -> &mut BaseWin;
fn to_self_ptr(c_void: *mut ::core::ffi::c_void) -> *mut Self;
fn raw_ptr_isize(ptr: *mut Self) -> isize;
fn show(&self) -> bool {
unsafe {
ShowWindow(self.get_hwnd(), SW_NORMAL).as_bool()
}
}
fn update(&self) -> bool {
unsafe { UpdateWindow(self.get_hwnd()).as_bool() }
}
fn invalidate(&self, erase: bool) -> bool {
unsafe { InvalidateRect(self.get_hwnd(), None, erase).as_bool() }
}
fn do_idle(&mut self) -> bool {
false
}
fn on_paint(&self, _hdc: &mut DeviceContext, _rect: &mut RECT) -> EventHandled {
EventHandled::NotHandled
}
fn on_create(&mut self, _event: &Event) -> EventHandled {
EventHandled::NotHandled
}
fn on_destroy(&self, _event: &Event) -> EventHandled {
println!("WM_DESTROY");
unsafe {
PostQuitMessage(0);
}
EventHandled::Handled(LRESULT(0))
}
fn on_resize(&mut self, _x: i32, _y: i32) -> EventHandled {
EventHandled::NotHandled
}
fn on_command(&self, event: &CommandEvent) -> EventHandled {
println!("command... {:?}", event);
match event.command {
100 => {
self.send_message(SendMessageParams::Close);
EventHandled::Handled(LRESULT(0))
}
_ => EventHandled::NotHandled,
}
}
fn on_mouse(&mut self, _event: MouseEvent) -> EventHandled {
EventHandled::NotHandled
}
fn on_kbd(&mut self, _event: KbdEvent) -> EventHandled {
EventHandled::NotHandled
}
fn send_message(&self, message: SendMessageParams) {
let (msg, wparam, lparam) = match message {
SendMessageParams::Close => (WM_CLOSE, WPARAM(0), LPARAM(0)),
};
unsafe {
SendMessageW(self.get_hwnd(), msg, wparam, lparam);
}
}
fn on_ncdestroy(&self, _event: &super::Event) -> EventHandled {
EventHandled::NotHandled
}
fn get_client_rect(&self) -> Result<RECT> {
let mut rect = RECT::default();
unsafe {
GetClientRect(self.get_hwnd(), &mut rect)?;
}
Ok(rect)
}
fn create_window(&mut self, title: PCWSTR) -> Result<HWND>;
fn create_win(&mut self, title: PCWSTR, create_args: WinCreateArgs) -> Result<HWND> {
let hwnd: HWND;
let class_name = create_args.class_name;
let hinst = create_args.instance;
let brush: HGDIOBJ;
unsafe {
brush = GetStockObject(WHITE_BRUSH);
}
let brush = HBRUSH(brush.0);
let icon = match create_args.icon {
None => load_icon(create_args.instance, IDI_APPLICATION),
Some(icon_name) => load_icon(create_args.instance, icon_name),
};
let icon = match icon {
Err(_) => HICON(0),
Ok(icon) => icon,
};
unsafe {
let wc = WNDCLASSEXW {
hCursor: create_args.cursor,
hIcon: icon,
hInstance: create_args.instance,
lpszClassName: create_args.class_name,
hbrBackground: brush,
style: CS_HREDRAW | CS_VREDRAW,
lpfnWndProc: Some(Self::wndproc),
cbSize: mem::size_of::<WNDCLASSEXW>() as u32,
lpszMenuName: create_args.menu_name,
..Default::default()
};
let atom = RegisterClassExW(&wc);
debug_assert!(atom != 0);
hwnd = CreateWindowExW(
create_args.ex_style, class_name,
title,
create_args.style,
CW_USEDEFAULT,
CW_USEDEFAULT,
create_args.window_width,
create_args.window_height,
None,
None,
hinst,
Some(self as *const _ as _),
);
}
Ok(hwnd)
}
fn dispatch_event(&mut self, event: &Event) -> LRESULT {
if self.get_canary() != 99 {
println!("error: canary is not 99!");
return LRESULT(1);
}
let processed_event = match event.message {
WM_CREATE => {
self.get_base().on_create(event);
self.on_create(event)
}
WM_PAINT => {
let mut hdc = DeviceContext::begin_paint(self.get_hwnd());
let handled = match self.get_client_rect() {
Err(err) => {
println!("error getting client rect: {:?}", err);
EventHandled::NotHandled
}
Ok(mut rect) => self.on_paint(&mut hdc, &mut rect),
};
handled
}
WM_SIZE => {
let x = lword(event.lparam.0);
let y = hword(event.lparam.0);
self.get_base().on_resize(x, y);
self.on_resize(x, y)
}
WM_DESTROY => self.on_destroy(event),
WM_NCDESTROY => self.on_ncdestroy(event),
WM_COMMAND => {
let command_type = match hword(event.wparam.0 as isize) {
0 => SourceType::Menu,
1 => SourceType::Accelerator,
_ => SourceType::Control,
};
let command_event = CommandEvent {
command: lword(event.wparam.0 as isize),
control_hwnd: if command_type == SourceType::Control {
Some(HWND(event.lparam.0))
} else {
None
},
source_type: command_type,
};
self.on_command(&command_event)
}
WM_MOUSEMOVE | WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK | WM_RBUTTONDOWN
| WM_RBUTTONUP | WM_RBUTTONDBLCLK | WM_MBUTTONDBLCLK | WM_MBUTTONDOWN
| WM_MBUTTONUP => self.on_mouse(MouseEvent::new(event)),
WM_KEYDOWN | WM_KEYUP | WM_CHAR | WM_DEADCHAR => self.on_kbd(KbdEvent::new(event)),
_ => EventHandled::NotHandled,
};
if event.message == WM_NCDESTROY {
println!("WM_NCDESTROY");
unsafe {
SetWindowLongPtrW(event.hwnd, GWLP_USERDATA, 0);
}
self.set_hwnd(HWND(0));
return unsafe {
DefWindowProcW(event.hwnd, event.message, event.wparam, event.lparam)
};
}
match processed_event {
EventHandled::NotHandled => unsafe {
DefWindowProcW(event.hwnd, event.message, event.wparam, event.lparam)
},
EventHandled::Handled(lresult) => lresult,
}
}
extern "system" fn wndproc(
hwnd: HWND,
message: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
unsafe {
if hwnd.0 == 0 {
return DefWindowProcW(hwnd, message, wparam, lparam);
}
}
let ptr_self = match message {
WM_NCCREATE => {
println!("NC Create");
unsafe {
let createstruct = &mut *(lparam.0 as *mut CREATESTRUCTW);
println!("nc create raw_ptr: {:?}", createstruct.lpCreateParams);
let ptr_self = Self::to_self_ptr(createstruct.lpCreateParams);
SetWindowLongPtrW(hwnd, GWLP_USERDATA, Self::raw_ptr_isize(ptr_self));
let ref_self = &mut *ptr_self;
ref_self.set_hwnd(hwnd.clone());
ptr_self
}
}
_ => unsafe {
Self::to_self_ptr(GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut ::core::ffi::c_void)
},
};
if ptr_self.is_null() {
println!("ptr_self is null");
unsafe {
return DefWindowProcW(hwnd, message, wparam, lparam);
}
}
let ref_self: &mut Self;
unsafe {
ref_self = &mut *ptr_self;
}
let event = super::Event {
hwnd: hwnd,
message: message,
wparam: wparam,
lparam: lparam,
};
ref_self.dispatch_event(&event)
}
}