use super::*;
use winapi::um::winuser::{
AdjustWindowRect, BeginPaint, CreateWindowExW, DispatchMessageW, EndPaint, GetClientRect,
GetCursorPos, GetDC, GetMessageW, PeekMessageW, PostQuitMessage, RegisterClassW, ReleaseDC,
ScreenToClient, SetCursorPos, TranslateMessage, MSG, PAINTSTRUCT,
};
#[inline]
pub fn adjust_window_rect(rect: &mut EdgeRect, style: u32, menu: bool) -> Result<(), ErrorCode> {
let output = unsafe { AdjustWindowRect(rect as *mut EdgeRect as *mut RECT, style, menu as i32) };
if output != 0 {
Ok(())
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn begin_paint(hwnd: HWND, paint: &mut PAINTSTRUCT) -> Option<HDC> {
let hdc = BeginPaint(hwnd, paint);
if hdc.is_null() {
None
} else {
Some(hdc)
}
}
#[derive(Clone, Copy)]
pub struct CreateWindowExWRequest<'a> {
ex_style: u32,
class_name: &'a str,
window_name: &'a str,
style: u32,
x: i32,
y: i32,
width: i32,
height: i32,
parent: Option<HWND>,
menu: Option<HMENU>,
instance: Option<HINSTANCE>,
lparam: Option<NonNull<c_void>>,
}
pub unsafe fn create_window_ex(request: CreateWindowExWRequest) -> Result<HWND, ErrorCode> {
let class_name_wide_null: Vec<u16> = wide_null(request.class_name);
let window_name_wide_null: Vec<u16> = wide_null(request.window_name);
let hwnd = CreateWindowExW(
request.ex_style,
class_name_wide_null.as_ptr(),
window_name_wide_null.as_ptr(),
request.style,
request.x,
request.y,
request.width,
request.height,
request.parent.unwrap_or(null_mut()),
request.menu.unwrap_or(null_mut()),
request
.instance
.unwrap_or_else(|| winapi::um::libloaderapi::GetModuleHandleW(null())),
core::mem::transmute(request.lparam),
);
if hwnd.is_null() {
Err(get_last_error())
} else {
Ok(hwnd)
}
}
#[inline]
pub unsafe fn dispatch_message(msg: &MSG) -> isize {
DispatchMessageW(msg)
}
#[inline]
pub unsafe fn end_paint(hwnd: HWND, paint: &PAINTSTRUCT) {
EndPaint(hwnd, paint);
}
#[inline]
pub unsafe fn get_client_rect(hwnd: HWND, rect: &mut EdgeRect) -> Result<(), ErrorCode> {
if GetClientRect(hwnd, rect as *mut EdgeRect as *mut RECT) != 0 {
Ok(())
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn get_cursor_pos() -> Result<Point, ErrorCode> {
let mut p = Point { x: 0, y: 0 };
let result = GetCursorPos(&mut p as *mut Point as *mut POINT);
if result != 0 {
Ok(p)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn get_dc(hwnd: HWND) -> Option<HDC> {
let output = GetDC(hwnd);
if output.is_null() {
None
} else {
Some(output)
}
}
#[inline]
pub unsafe fn get_message(
msg: &mut MSG,
hwnd: HWND,
min: u32,
max: u32,
) -> Result<bool, ErrorCode> {
let output = GetMessageW(msg, hwnd, min, max);
if output > 0 {
Ok(true)
} else if output == 0 {
Ok(false)
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn peek_message(msg: &mut MSG, hwnd: HWND, min: u32, max: u32, remove: u32) -> bool {
PeekMessageW(msg, hwnd, min, max, remove) != 0
}
#[inline]
pub unsafe fn post_quit_message(exit_code: i32) {
PostQuitMessage(exit_code)
}
#[derive(Clone, Copy)]
pub struct WinClassW<'a> {
style: u32,
wnd_proc: Option<unsafe extern "system" fn(HWND, u32, usize, isize) -> isize>,
class_bytes: usize,
window_bytes: usize,
instance: Option<HINSTANCE>,
icon: Option<HICON>,
cursor: Option<HCURSOR>,
background: Option<HBRUSH>,
menu_name: &'a str,
class_name: &'a str,
}
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
pub unsafe fn register_class(request: WinClassW) -> Result<Atom, ErrorCode> {
let menu_name_wide_null: Vec<u16> = wide_null(request.menu_name);
let class_name_wide_null: Vec<u16> = wide_null(request.class_name);
let mut class: WNDCLASSW = core::mem::zeroed();
class.style = request.style;
class.lpfnWndProc = request.wnd_proc;
class.cbClsExtra =
i32::try_from(request.class_bytes).map_err(|_| ErrorCode(ErrorCode::APPLICATION_ERROR_BIT))?;
class.cbWndExtra =
i32::try_from(request.window_bytes).map_err(|_| ErrorCode(ErrorCode::APPLICATION_ERROR_BIT))?;
class.hInstance = match request.instance {
Some(instance) => instance,
None => get_module_handle(None)?,
};
class.hIcon = request.icon.unwrap_or(null_mut());
class.hCursor = request.cursor.unwrap_or(null_mut());
class.hbrBackground = request.background.unwrap_or(null_mut());
class.lpszMenuName = menu_name_wide_null.as_ptr();
class.lpszClassName = class_name_wide_null.as_ptr();
let output = RegisterClassW(&class);
if output != 0 {
Ok(Atom(output))
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn release_dc(hwnd: HWND, hdc: HDC) -> Result<(), ()> {
if ReleaseDC(hwnd, hdc) == 1 {
Ok(())
} else {
Err(())
}
}
#[inline]
pub unsafe fn screen_to_client(hwnd: HWND, coord: &mut Point) -> Result<(), ()> {
if ScreenToClient(hwnd, coord as *mut Point as *mut POINT) != 0 {
Ok(())
} else {
Err(())
}
}
#[inline]
pub unsafe fn set_cursor_pos(x: i32, y: i32) -> Result<(), ErrorCode> {
if SetCursorPos(x, y) != 0 {
Ok(())
} else {
Err(get_last_error())
}
}
#[inline]
pub unsafe fn translate_message(msg: &MSG) -> bool {
TranslateMessage(msg) != 0
}