use cursor_icon::CursorIcon;
use windows::{
core::{HSTRING, PCWSTR},
Win32::{
Foundation::HINSTANCE,
UI::WindowsAndMessaging::{
self, GetClassInfoExW, LoadCursorW, RegisterClassExW, UnregisterClassW,
CW_USEDEFAULT, HCURSOR, WNDCLASSEXW,
},
},
};
use crate::{
flag::WindowClassStyle,
handle::Instance,
procedure::{self},
};
pub struct Registered;
pub struct Unregistered;
pub struct WindowClass {
instance: Instance,
name: String,
}
impl WindowClass {
pub fn new(desc: &WindowClassDescriptor) -> Self {
let name = HSTRING::from(desc.name.clone());
let wc = WNDCLASSEXW {
cbSize: core::mem::size_of::<WNDCLASSEXW>() as _,
hInstance: desc.instance.into(),
lpszClassName: PCWSTR(name.as_ptr()),
lpfnWndProc: Some(procedure::window_procedure),
style: desc.style.into(),
hCursor: unsafe {
LoadCursorW(None, PCWSTR(desc.cursor.to_cursor().0.cast())).unwrap()
},
..Default::default()
};
unsafe { RegisterClassExW(&wc) };
Self {
instance: desc.instance,
name: desc.name.clone(),
}
}
pub fn get(instance: &Instance, name: String) -> Result<Self, windows::core::Error> {
let hstring = HSTRING::from(name.clone());
let mut class = WNDCLASSEXW::default();
let result =
unsafe { GetClassInfoExW(HINSTANCE::from(*instance), &hstring, &mut class) };
result.map(|_| Self {
instance: *instance,
name,
})
}
pub fn unregister(self) -> Result<(), windows::core::Error> {
let hstring = HSTRING::from(self.name);
unsafe {
UnregisterClassW(PCWSTR(hstring.as_ptr()), HINSTANCE::from(self.instance))
}?;
Ok(())
}
pub fn name(&self) -> &String {
&self.name
}
pub fn instance(&self) -> &Instance {
&self.instance
}
}
pub struct WindowClassDescriptor {
pub instance: Instance,
pub name: String,
pub style: WindowClassStyle,
pub cursor: CursorIcon,
}
impl Default for WindowClassDescriptor {
fn default() -> Self {
Self {
instance: Default::default(),
name: "Window Class".to_owned(),
style: WindowClassStyle::HorizontalRedraw | WindowClassStyle::VerticalRedraw,
cursor: Default::default(),
}
}
}
impl WindowClassDescriptor {
pub fn with_instance(self, instance: Instance) -> Self {
Self { instance, ..self }
}
pub fn with_name(self, name: impl Into<String>) -> Self {
Self {
name: name.into(),
..self
}
}
pub fn with_style(self, style: WindowClassStyle) -> Self {
Self { style, ..self }
}
pub fn with_cursor(self, cursor: CursorIcon) -> Self {
Self { cursor, ..self }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Size {
pub width: i32,
pub height: i32,
}
impl Size {
pub const AUTO: Self = Self {
width: CW_USEDEFAULT,
height: CW_USEDEFAULT,
};
}
impl From<[i32; 2]> for Size {
fn from([width, height]: [i32; 2]) -> Self {
Self { width, height }
}
}
impl From<(i32, i32)> for Size {
fn from((width, height): (i32, i32)) -> Self {
Self { width, height }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Position {
pub x: i32,
pub y: i32,
}
impl Position {
pub const AUTO: Self = Self {
x: CW_USEDEFAULT,
y: CW_USEDEFAULT,
};
}
impl From<[i32; 2]> for Position {
fn from([x, y]: [i32; 2]) -> Self {
Self { x, y }
}
}
impl From<(i32, i32)> for Position {
fn from((x, y): (i32, i32)) -> Self {
Self { x, y }
}
}
trait ToHCURSOR {
fn to_cursor(&self) -> HCURSOR;
}
impl ToHCURSOR for CursorIcon {
fn to_cursor(&self) -> HCURSOR {
match self {
CursorIcon::Default => {
HCURSOR(WindowsAndMessaging::IDC_ARROW.as_ptr().cast_mut().cast())
}
CursorIcon::ContextMenu => todo!(),
CursorIcon::Help => todo!(),
CursorIcon::Pointer => todo!(),
CursorIcon::Progress => todo!(),
CursorIcon::Wait => todo!(),
CursorIcon::Cell => todo!(),
CursorIcon::Crosshair => todo!(),
CursorIcon::Text => todo!(),
CursorIcon::VerticalText => todo!(),
CursorIcon::Alias => todo!(),
CursorIcon::Copy => todo!(),
CursorIcon::Move => todo!(),
CursorIcon::NoDrop => todo!(),
CursorIcon::NotAllowed => todo!(),
CursorIcon::Grab => todo!(),
CursorIcon::Grabbing => todo!(),
CursorIcon::EResize => todo!(),
CursorIcon::NResize => todo!(),
CursorIcon::NeResize => todo!(),
CursorIcon::NwResize => todo!(),
CursorIcon::SResize => todo!(),
CursorIcon::SeResize => todo!(),
CursorIcon::SwResize => todo!(),
CursorIcon::WResize => todo!(),
CursorIcon::EwResize => todo!(),
CursorIcon::NsResize => todo!(),
CursorIcon::NeswResize => todo!(),
CursorIcon::NwseResize => todo!(),
CursorIcon::ColResize => todo!(),
CursorIcon::RowResize => todo!(),
CursorIcon::AllScroll => todo!(),
CursorIcon::ZoomIn => todo!(),
CursorIcon::ZoomOut => todo!(),
_ => todo!(),
}
}
}