use super::{
InstanceHandle,
window::{
WindowHandle,
default_window_procedure,
},
icon::IconHandle,
cursor::CursorHandle,
brush::BrushHandle,
};
use core::{
mem::{
size_of,
transmute,
transmute_copy,
},
ptr::null_mut,
num::{
NonZeroU16,
NonZeroIsize,
},
};
use winapi::{
um::{
winuser::{
RegisterClassExW,
UnregisterClassW,
GetClassInfoExW,
CS_HREDRAW,
CS_VREDRAW,
CS_DBLCLKS,
CS_OWNDC,
CS_CLASSDC,
CS_PARENTDC,
CS_NOCLOSE,
CS_SAVEBITS,
CS_BYTEALIGNCLIENT,
CS_BYTEALIGNWINDOW,
CS_GLOBALCLASS,
CS_DROPSHADOW,
COLOR_ACTIVEBORDER,
COLOR_ACTIVECAPTION,
COLOR_APPWORKSPACE,
COLOR_BACKGROUND,
COLOR_BTNFACE,
COLOR_BTNSHADOW,
COLOR_BTNTEXT,
COLOR_CAPTIONTEXT,
COLOR_GRAYTEXT,
COLOR_HIGHLIGHT,
COLOR_HIGHLIGHTTEXT,
COLOR_INACTIVEBORDER,
COLOR_INACTIVECAPTION,
COLOR_MENU,
COLOR_MENUTEXT,
COLOR_SCROLLBAR,
COLOR_WINDOW,
COLOR_WINDOWFRAME,
COLOR_WINDOWTEXT,
},
}
};
#[repr(u32)]
#[derive(Copy,Clone,Debug)]
pub enum WindowClassStyle{
VerticalRedraw=CS_VREDRAW,
HorizontalRedraw=CS_HREDRAW,
DoubleClicks=CS_DBLCLKS,
OwnDeviceContext=CS_OWNDC,
ClassDeviceContext=CS_CLASSDC,
ParentDeviceContext=CS_PARENTDC,
NoClose=CS_NOCLOSE,
SaveBits=CS_SAVEBITS,
ByteAlignClient=CS_BYTEALIGNCLIENT,
ByteAlignWindow=CS_BYTEALIGNWINDOW,
GlobalClass=CS_GLOBALCLASS,
DropShadow=CS_DROPSHADOW,
}
#[derive(Clone,Copy,Debug)]
pub struct WindowClassStyles{
flag:u32
}
impl WindowClassStyles{
pub const fn new()->WindowClassStyles{
Self{
flag:0u32,
}
}
pub const fn set(mut self,style:WindowClassStyle)->WindowClassStyles{
self.flag|=style as u32;
self
}
pub const fn remove(mut self,style:WindowClassStyle)->WindowClassStyles{
self.flag&=!(style as u32);
self
}
}
pub struct ClassIdentifier{
identifier:isize,
}
impl ClassIdentifier{
#[inline(always)]
pub fn name(name:*const u16)->ClassIdentifier{
Self{
identifier:name as isize,
}
}
#[inline(always)]
pub fn atom(atom:ClassAtom)->ClassIdentifier{
Self{
identifier:atom.as_raw() as isize,
}
}
pub const fn as_ptr(&self)->*const u16{
self.identifier as *const u16
}
}
#[derive(Clone,Copy)]
#[repr(transparent)]
pub struct ClassAtom{
inner:NonZeroU16
}
impl ClassAtom{
#[inline(always)]
pub fn from_raw(raw:u16)->Option<ClassAtom>{
unsafe{
transmute(raw)
}
}
#[inline(always)]
pub unsafe fn from_raw_unchecked(raw:u16)->ClassAtom{
transmute(raw)
}
#[inline(always)]
pub fn to_raw(handle:Option<ClassAtom>)->u16{
unsafe{
transmute(handle)
}
}
#[inline(always)]
pub fn as_raw(&self)->u16{
unsafe{
transmute_copy(self)
}
}
}
#[derive(Copy,Clone,Debug)]
#[repr(i32)]
pub enum WindowBackgroundSystemColour{
ActiveBorder=COLOR_ACTIVEBORDER,
ActioveCaption=COLOR_ACTIVECAPTION,
AppWorkspace=COLOR_APPWORKSPACE,
Background=COLOR_BACKGROUND,
ButtonFace=COLOR_BTNFACE,
ButtonShadow=COLOR_BTNSHADOW,
ButtonText=COLOR_BTNTEXT,
CaptionText=COLOR_CAPTIONTEXT,
GrayText=COLOR_GRAYTEXT,
Highlight=COLOR_HIGHLIGHT,
HighlightText=COLOR_HIGHLIGHTTEXT,
InactiveBorder=COLOR_INACTIVEBORDER,
InactioveCaption=COLOR_INACTIVECAPTION,
Menu=COLOR_MENU,
MenuText=COLOR_MENUTEXT,
Scrollbar=COLOR_SCROLLBAR,
Window=COLOR_WINDOW,
WindowFrame=COLOR_WINDOWFRAME,
WindowText=COLOR_WINDOWTEXT,
}
#[derive(Clone,Copy,Debug)]
#[repr(transparent)]
pub struct WindowBackgroundColour{
inner:NonZeroIsize,
}
impl WindowBackgroundColour{
#[inline(always)]
pub fn system_colour(colour:WindowBackgroundSystemColour)->WindowBackgroundColour{
Self{
inner:unsafe{transmute(colour as isize+1)}
}
}
#[inline(always)]
pub fn brush(brush:BrushHandle)->WindowBackgroundColour{
Self{
inner:unsafe{transmute(brush.as_raw())}
}
}
}
#[derive(Clone)]
#[repr(C)]
pub struct WindowClassInfo{
size:u32,
pub styles:WindowClassStyles,
pub window_procedure:unsafe extern "system" fn(WindowHandle,u32,usize,isize)->isize,
pub extra_class_data:i32,
pub extra_window_data:i32,
pub instance:Option<InstanceHandle>,
pub icon:Option<IconHandle>,
pub cursor:Option<CursorHandle>,
pub background:Option<WindowBackgroundColour>,
pub menu_name:*const u16,
pub class_name:*const u16,
pub small_icon:Option<IconHandle>,
}
impl WindowClassInfo{
pub fn new()->WindowClassInfo{
Self{
size:size_of::<WindowClassInfo>() as u32,
styles:WindowClassStyles::new(),
window_procedure:default_window_procedure,
extra_class_data:0i32,
extra_window_data:0i32,
instance:None,
icon:None,
cursor:None,
background:None,
menu_name:null_mut(),
class_name:null_mut(),
small_icon:None,
}
}
}
pub struct WindowClass;
impl WindowClass{
pub const fn new()->WindowClass{
Self
}
pub fn register(
&self,
class_name:*const u16,
styles:WindowClassStyles,
window_procedure:unsafe extern "system" fn(WindowHandle,u32,usize,isize)->isize,
extra_class_data:i32,
extra_window_data:i32,
instance:Option<InstanceHandle>,
icon:Option<IconHandle>,
small_icon:Option<IconHandle>,
cursor:Option<CursorHandle>,
background:Option<WindowBackgroundColour>,
menu_name:*const u16,
)->Option<ClassAtom>{
let mut attributes=WindowClassInfo::new();
attributes.styles=styles;
attributes.window_procedure=window_procedure;
attributes.extra_class_data=extra_class_data;
attributes.extra_window_data=extra_window_data;
attributes.instance=instance;
attributes.icon=icon;
attributes.cursor=cursor;
attributes.background=background;
attributes.menu_name=menu_name;
attributes.class_name=class_name;
attributes.small_icon=small_icon;
unsafe{
ClassAtom::from_raw(RegisterClassExW(transmute(&attributes)))
}
}
#[inline(always)]
pub fn register_indirect(&self,info:&WindowClassInfo)->Option<ClassAtom>{
unsafe{
ClassAtom::from_raw(RegisterClassExW(transmute(&info)))
}
}
#[inline(always)]
pub fn unregister(&self,class:ClassIdentifier,instance:Option<InstanceHandle>)->bool{
unsafe{
UnregisterClassW(class.identifier as *const _,InstanceHandle::to_raw(instance))!=0
}
}
#[inline(always)]
pub fn get_info(
&self,
class:ClassIdentifier,
instance:Option<InstanceHandle>,
info:&mut WindowClassInfo
)->bool{
unsafe{
GetClassInfoExW(
InstanceHandle::to_raw(instance),
class.identifier as *const _,
transmute(info)
)!=0
}
}
}