#![cfg(feature = "winuser")]
use super::*;
use winapi::um::winuser::{
AdjustWindowRect, BeginPaint, ClipCursor, CreateWindowExW, DefWindowProcW,
DispatchMessageW, EndPaint, GetClientRect, GetCursorPos, GetDC, GetMessageW,
LoadCursorW, PeekMessageW, PostQuitMessage, RegisterClassW, ReleaseDC,
ScreenToClient, SetCursorPos, TranslateMessage, PAINTSTRUCT, WNDCLASSW, WS_BORDER,
WS_CAPTION, WS_CHILD, WS_CHILDWINDOW, WS_CLIPCHILDREN, WS_CLIPSIBLINGS,
WS_DISABLED, WS_DLGFRAME, WS_GROUP, WS_HSCROLL, WS_ICONIC, WS_MAXIMIZE,
WS_MAXIMIZEBOX, WS_MINIMIZE, WS_MINIMIZEBOX, WS_OVERLAPPEDWINDOW, WS_POPUP,
WS_POPUPWINDOW, WS_SIZEBOX, WS_SYSMENU, WS_TABSTOP, WS_THICKFRAME, WS_TILEDWINDOW,
WS_VISIBLE, WS_VSCROLL,
};
pub use winapi::um::winuser::{CW_USEDEFAULT, IDC_ARROW, MSG, WM_DESTROY};
#[derive(Debug, Clone, Copy, Default)]
pub struct WindowStyle(pub u32);
#[rustfmt::skip]
impl WindowStyle {
mk_newtype_bitflag32!(WS_BORDER, border, with_border, set_border);
mk_newtype_bitflag32!(WS_CAPTION, caption, with_caption, set_caption);
mk_newtype_bitflag32!(WS_CHILD, child, with_child, set_child);
mk_newtype_bitflag32!(WS_CHILDWINDOW, child_window, with_child_window, set_child_window);
mk_newtype_bitflag32!(WS_CLIPCHILDREN, clip_children, with_clip_children, set_clip_children);
mk_newtype_bitflag32!(WS_CLIPSIBLINGS, clip_siblings, with_clip_siblings, set_clip_siblings);
mk_newtype_bitflag32!(WS_DISABLED, disabled, with_disabled, set_disabled);
mk_newtype_bitflag32!(WS_DLGFRAME, dlg_frame, with_dlg_frame, set_dlg_frame);
mk_newtype_bitflag32!(WS_GROUP, group, with_group, set_group);
mk_newtype_bitflag32!(WS_HSCROLL, h_scroll, with_h_scroll, set_h_scroll);
mk_newtype_bitflag32!(WS_ICONIC, iconic, with_iconic, set_iconic);
mk_newtype_bitflag32!(WS_MAXIMIZE, maximize, with_maximize, set_maximize);
mk_newtype_bitflag32!(WS_MAXIMIZEBOX, maximize_box, with_maximize_box, set_maximize_box);
mk_newtype_bitflag32!(WS_MINIMIZE, minimize, with_minimize, set_minimize);
mk_newtype_bitflag32!(WS_MINIMIZEBOX, minimize_box, with_minimize_box, set_minimize_box);
mk_newtype_bitflag32!(WS_OVERLAPPEDWINDOW, overlapped_window, with_overlapped_window, set_overlapped_window);
mk_newtype_bitflag32!(WS_POPUP, popup, with_popup, set_popup);
mk_newtype_bitflag32!(WS_POPUPWINDOW, popup_window, with_popup_window, set_popup_window);
mk_newtype_bitflag32!(WS_SIZEBOX, size_box, with_size_box, set_size_box);
mk_newtype_bitflag32!(WS_SYSMENU, sys_menu, with_sys_menu, set_sys_menu);
mk_newtype_bitflag32!(WS_TABSTOP, tab_stop, with_tab_stop, set_tab_stop);
mk_newtype_bitflag32!(WS_THICKFRAME, thick_frame, with_thick_frame, set_thick_frame);
mk_newtype_bitflag32!(WS_TILEDWINDOW, tiled_window, with_tiled_window, set_tiled_window);
mk_newtype_bitflag32!(WS_VISIBLE, visible, with_visible, set_visible);
mk_newtype_bitflag32!(WS_VSCROLL, v_scroll, with_v_scroll, set_v_scroll);
}
#[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() {
Some(hdc)
} else {
None
}
}
#[inline]
pub unsafe fn clip_cursor(rect: &EdgeRect) -> Result<(), ErrorCode> {
let p: *const RECT = rect as *const _ as *const _;
let output = ClipCursor(p);
if output != 0 {
Ok(())
} else {
Err(get_last_error())
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct CreateWindowExRequest<'a> {
pub ex_style: u32,
pub class_name: &'a str,
pub window_name: &'a str,
pub style: WindowStyle,
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
pub parent: Option<HWND>,
pub menu: Option<HMENU>,
pub instance: Option<HINSTANCE>,
pub lparam: Option<NonNull<c_void>>,
}
pub unsafe fn create_window_ex(
request: CreateWindowExRequest,
) -> 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.0,
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(always)]
pub unsafe fn default_window_proc(
win: HWND,
msg: u32,
wparam: usize,
lparam: isize,
) -> isize {
DefWindowProcW(win, msg, wparam, lparam)
}
#[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);
match output {
0 => Ok(false),
_ if output > 0 => Ok(true),
_ => Err(get_last_error()),
}
}
pub unsafe fn load_cursor(
instance: HINSTANCE,
name: *const u16,
) -> Result<HCURSOR, ErrorCode> {
let output = LoadCursorW(instance, name);
if !output.is_null() {
Ok(output)
} 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)
}
#[allow(missing_debug_implementations)]
#[derive(Clone, Copy, Default)]
pub struct WinClass<'a> {
pub style: u32,
pub wnd_proc: Option<unsafe extern "system" fn(HWND, u32, usize, isize) -> isize>,
pub class_bytes: usize,
pub window_bytes: usize,
pub instance: Option<HINSTANCE>,
pub icon: Option<HICON>,
pub cursor: Option<HCURSOR>,
pub background: Option<HBRUSH>,
pub menu_name: &'a str,
pub class_name: &'a str,
}
pub unsafe fn register_class(request: WinClass) -> 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
}
pub use winapi::um::winuser::{
VK_ACCEPT, VK_ADD, VK_APPS, VK_ATTN, VK_BACK, VK_BROWSER_BACK,
VK_BROWSER_FAVORITES, VK_BROWSER_FORWARD, VK_BROWSER_HOME, VK_BROWSER_REFRESH,
VK_BROWSER_SEARCH, VK_BROWSER_STOP, VK_CANCEL, VK_CAPITAL, VK_CLEAR, VK_CONTROL,
VK_CONVERT, VK_CRSEL, VK_DECIMAL, VK_DELETE, VK_DIVIDE, VK_DOWN, VK_END, VK_EREOF,
VK_ESCAPE, VK_EXECUTE, VK_EXSEL, VK_F1, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14,
VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21, VK_F22, VK_F23,
VK_F24, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_FINAL, VK_GAMEPAD_A,
VK_GAMEPAD_B, VK_GAMEPAD_DPAD_DOWN, VK_GAMEPAD_DPAD_LEFT, VK_GAMEPAD_DPAD_RIGHT,
VK_GAMEPAD_DPAD_UP, VK_GAMEPAD_LEFT_SHOULDER, VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON,
VK_GAMEPAD_LEFT_THUMBSTICK_DOWN, VK_GAMEPAD_LEFT_THUMBSTICK_LEFT,
VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT, VK_GAMEPAD_LEFT_THUMBSTICK_UP,
VK_GAMEPAD_LEFT_TRIGGER, VK_GAMEPAD_MENU, VK_GAMEPAD_RIGHT_SHOULDER,
VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON, VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN,
VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT, VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT,
VK_GAMEPAD_RIGHT_THUMBSTICK_UP, VK_GAMEPAD_RIGHT_TRIGGER, VK_GAMEPAD_VIEW,
VK_GAMEPAD_X, VK_GAMEPAD_Y, VK_HANGEUL, VK_HANGUL, VK_HANJA, VK_HELP, VK_HOME,
VK_ICO_00, VK_ICO_CLEAR, VK_ICO_HELP, VK_INSERT, VK_JUNJA, VK_KANA, VK_KANJI,
VK_LAUNCH_APP1, VK_LAUNCH_APP2, VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT,
VK_LBUTTON, VK_LCONTROL, VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN, VK_MBUTTON,
VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE, VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP,
VK_MENU, VK_MODECHANGE, VK_MULTIPLY, VK_NAVIGATION_ACCEPT, VK_NAVIGATION_CANCEL,
VK_NAVIGATION_DOWN, VK_NAVIGATION_LEFT, VK_NAVIGATION_MENU, VK_NAVIGATION_RIGHT,
VK_NAVIGATION_UP, VK_NAVIGATION_VIEW, VK_NEXT, VK_NONAME, VK_NONCONVERT,
VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_OEM_1, VK_OEM_102,
VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5, VK_OEM_6, VK_OEM_7, VK_OEM_8, VK_OEM_ATTN,
VK_OEM_AUTO, VK_OEM_AX, VK_OEM_BACKTAB, VK_OEM_CLEAR, VK_OEM_COMMA, VK_OEM_COPY,
VK_OEM_CUSEL, VK_OEM_ENLW, VK_OEM_FINISH, VK_OEM_FJ_JISHO, VK_OEM_FJ_LOYA,
VK_OEM_FJ_MASSHOU, VK_OEM_FJ_ROYA, VK_OEM_FJ_TOUROKU, VK_OEM_JUMP, VK_OEM_MINUS,
VK_OEM_NEC_EQUAL, VK_OEM_PA1, VK_OEM_PA2, VK_OEM_PA3, VK_OEM_PERIOD, VK_OEM_PLUS,
VK_OEM_RESET, VK_OEM_WSCTRL, VK_PA1, VK_PACKET, VK_PAUSE, VK_PLAY, VK_PRINT,
VK_PRIOR, VK_PROCESSKEY, VK_RBUTTON, VK_RCONTROL, VK_RETURN, VK_RIGHT, VK_RMENU,
VK_RSHIFT, VK_RWIN, VK_SCROLL, VK_SELECT, VK_SEPARATOR, VK_SHIFT, VK_SLEEP,
VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_TAB, VK_UP, VK_VOLUME_DOWN, VK_VOLUME_MUTE,
VK_VOLUME_UP, VK_XBUTTON1, VK_XBUTTON2, VK_ZOOM,
};