update
This commit is contained in:
parent
ea09dc582d
commit
33d06b9cf8
|
@ -9,7 +9,7 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0.117", optional = true }
|
serde = { version = "1.0.117", optional = true }
|
||||||
serde_derive = { version = "1.0.117", optional = true }
|
serde_derive = { version = "1.0.117", optional = true }
|
||||||
lazy_static = "1.4.0"
|
once_cell = "1.5.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
with_serde = ["serde", "serde_derive"]
|
with_serde = ["serde", "serde_derive"]
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
use crate::windows;
|
use crate::windows;
|
||||||
use crate::{Event, EventType, HookCallback, Key, Robot};
|
use crate::{Event, EventType, HookCallback, Key, Robot};
|
||||||
use lazy_static::lazy_static;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::mem::{size_of, transmute_copy};
|
use std::mem::{size_of, transmute_copy};
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use winapi::ctypes::c_int;
|
use winapi::ctypes::c_int;
|
||||||
use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM};
|
use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM};
|
||||||
use winapi::shared::windef::HHOOK;
|
use winapi::shared::windef::HHOOK__;
|
||||||
use winapi::um::winuser::{
|
use winapi::um::winuser::{
|
||||||
CallNextHookEx, GetAsyncKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT, INPUT_KEYBOARD,
|
CallNextHookEx, GetAsyncKeyState, GetKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT,
|
||||||
KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT, WH_KEYBOARD_LL,
|
INPUT_KEYBOARD, KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT,
|
||||||
WM_KEYDOWN, WM_KEYUP,
|
WH_KEYBOARD_LL, WM_KEYDOWN, WM_KEYUP,
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
static KEY_2_VK_MAP: Lazy<HashMap<Key, WORD>> = Lazy::new(|| {
|
||||||
static ref KEY_2_VK_MAP: HashMap<Key, WORD> = {
|
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
m.insert(Key::Digit0, 0x30);
|
m.insert(Key::Digit0, 0x30);
|
||||||
m.insert(Key::Digit1, 0x31);
|
m.insert(Key::Digit1, 0x31);
|
||||||
|
@ -136,9 +135,9 @@ lazy_static! {
|
||||||
m.insert(Key::MetaLeft, 0x5B);
|
m.insert(Key::MetaLeft, 0x5B);
|
||||||
m.insert(Key::MetaRight, 0x5C);
|
m.insert(Key::MetaRight, 0x5C);
|
||||||
m
|
m
|
||||||
};
|
});
|
||||||
|
|
||||||
static ref VK_2_KEY_MAP: HashMap<WORD, Key> = {
|
static VK_2_KEY_MAP: Lazy<HashMap<WORD, Key>> = Lazy::new(|| {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
m.insert(0x30, Key::Digit0);
|
m.insert(0x30, Key::Digit0);
|
||||||
m.insert(0x31, Key::Digit1);
|
m.insert(0x31, Key::Digit1);
|
||||||
|
@ -256,25 +255,23 @@ lazy_static! {
|
||||||
m.insert(0x5B, Key::MetaLeft);
|
m.insert(0x5B, Key::MetaLeft);
|
||||||
m.insert(0x5C, Key::MetaRight);
|
m.insert(0x5C, Key::MetaRight);
|
||||||
m
|
m
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
fn default_callback(event: Event) {
|
fn default_callback(event: Event) {
|
||||||
println!("Default : Event {:?}", event);
|
println!("Default : Event {:?}", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut HOOK: HHOOK = null_mut();
|
static KEYBOARD_HHOOK: Lazy<AtomicPtr<HHOOK__>> = Lazy::new(AtomicPtr::default);
|
||||||
static mut HOOK_CALLBACK: HookCallback = default_callback;
|
static mut HOOK_CALLBACK: HookCallback = default_callback;
|
||||||
|
|
||||||
impl Robot {
|
impl Robot {
|
||||||
pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> {
|
pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> {
|
||||||
if HOOK.is_null() {
|
if KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||||
let r = windows::hook(WH_KEYBOARD_LL, Self::key_raw_callback);
|
let r = windows::hook(WH_KEYBOARD_LL, &*KEYBOARD_HHOOK, Self::key_raw_callback);
|
||||||
|
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
return Err(windows::HookError::Keyboard(r.err().unwrap()));
|
return Err(windows::HookError::Keyboard(r.err().unwrap()));
|
||||||
}
|
}
|
||||||
HOOK = r.ok().unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOK_CALLBACK = callback;
|
HOOK_CALLBACK = callback;
|
||||||
|
@ -283,12 +280,11 @@ impl Robot {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn key_unlisten() -> Result<(), windows::HookError> {
|
pub unsafe fn key_unlisten() -> Result<(), windows::HookError> {
|
||||||
if !HOOK.is_null() {
|
if !KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||||
let r = windows::unhook(HOOK);
|
let r = windows::unhook(&*KEYBOARD_HHOOK);
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
return Err(windows::HookError::Keyboard(r.err().unwrap()));
|
return Err(windows::HookError::Keyboard(r.err().unwrap()));
|
||||||
}
|
}
|
||||||
HOOK = null_mut();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOK_CALLBACK = default_callback;
|
HOOK_CALLBACK = default_callback;
|
||||||
|
@ -299,37 +295,13 @@ impl Robot {
|
||||||
pub fn key_press(key: Key) {
|
pub fn key_press(key: Key) {
|
||||||
let dw_flags = KEYEVENTF_SCANCODE;
|
let dw_flags = KEYEVENTF_SCANCODE;
|
||||||
|
|
||||||
let mut input = INPUT {
|
Self::keyboard_event(0, Self::key_to_scancode(key), dw_flags);
|
||||||
type_: INPUT_KEYBOARD,
|
|
||||||
u: unsafe {
|
|
||||||
transmute_copy(&KEYBDINPUT {
|
|
||||||
wVk: 0,
|
|
||||||
wScan: Self::key_to_scancode(key),
|
|
||||||
dwFlags: dw_flags,
|
|
||||||
time: 0,
|
|
||||||
dwExtraInfo: 0,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
|
||||||
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key_release(key: Key) {
|
pub fn key_release(key: Key) {
|
||||||
let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
|
let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
|
||||||
|
|
||||||
let mut input = INPUT {
|
Self::keyboard_event(0, Self::key_to_scancode(key), dw_flags);
|
||||||
type_: INPUT_KEYBOARD,
|
|
||||||
u: unsafe {
|
|
||||||
transmute_copy(&KEYBDINPUT {
|
|
||||||
wVk: 0,
|
|
||||||
wScan: Self::key_to_scancode(key),
|
|
||||||
dwFlags: dw_flags,
|
|
||||||
time: 0,
|
|
||||||
dwExtraInfo: 0,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
|
||||||
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key_pressed(key: Key) -> bool {
|
pub fn key_pressed(key: Key) -> bool {
|
||||||
|
@ -339,6 +311,29 @@ impl Robot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn key_toggled(key: Key) -> bool {
|
||||||
|
match Self::key_2_virtual_key(key) {
|
||||||
|
Some(vk) => (unsafe { GetKeyState(vk as i32) & 15 != 0 }),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keyboard_event(vk: u16, scan: u16, dw_flags: u32) {
|
||||||
|
let mut input = INPUT {
|
||||||
|
type_: INPUT_KEYBOARD,
|
||||||
|
u: unsafe {
|
||||||
|
transmute_copy(&KEYBDINPUT {
|
||||||
|
wVk: vk,
|
||||||
|
wScan: scan,
|
||||||
|
dwFlags: dw_flags,
|
||||||
|
time: 0,
|
||||||
|
dwExtraInfo: 0,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
};
|
||||||
|
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
||||||
|
}
|
||||||
|
|
||||||
fn key_to_scancode(key: Key) -> u16 {
|
fn key_to_scancode(key: Key) -> u16 {
|
||||||
match Self::key_2_virtual_key(key) {
|
match Self::key_2_virtual_key(key) {
|
||||||
Some(vk) => unsafe { MapVirtualKeyW(vk as u32, 0) as u16 },
|
Some(vk) => unsafe { MapVirtualKeyW(vk as u32, 0) as u16 },
|
||||||
|
@ -353,11 +348,28 @@ impl Robot {
|
||||||
|
|
||||||
unsafe extern "system" fn key_raw_callback(
|
unsafe extern "system" fn key_raw_callback(
|
||||||
code: c_int,
|
code: c_int,
|
||||||
param: WPARAM,
|
w_param: WPARAM,
|
||||||
lpdata: LPARAM,
|
l_param: LPARAM,
|
||||||
) -> LRESULT {
|
) -> LRESULT {
|
||||||
if code == HC_ACTION {
|
if code == HC_ACTION {
|
||||||
let opt = Self::key_convert(param, lpdata);
|
let opt = match w_param as u32 {
|
||||||
|
WM_KEYDOWN => {
|
||||||
|
let code = Self::get_virtual_key(l_param);
|
||||||
|
match Self::virtual_key_2_key(code as u16) {
|
||||||
|
Some(k) => Some(EventType::KeyPress(k)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WM_KEYUP => {
|
||||||
|
let code = Self::get_virtual_key(l_param);
|
||||||
|
match Self::virtual_key_2_key(code as u16) {
|
||||||
|
Some(k) => Some(EventType::KeyRelease(k)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(event_type) = opt {
|
if let Some(event_type) = opt {
|
||||||
let event = Event {
|
let event = Event {
|
||||||
event_type,
|
event_type,
|
||||||
|
@ -366,27 +378,7 @@ impl Robot {
|
||||||
HOOK_CALLBACK(event);
|
HOOK_CALLBACK(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallNextHookEx(HOOK, code, param, lpdata)
|
CallNextHookEx(null_mut(), code, w_param, l_param)
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn key_convert(wparam: WPARAM, lparam: LPARAM) -> Option<EventType> {
|
|
||||||
match wparam.try_into() {
|
|
||||||
Ok(WM_KEYDOWN) => {
|
|
||||||
let code = Self::get_virtual_key(lparam);
|
|
||||||
match Self::virtual_key_2_key(code as u16) {
|
|
||||||
Some(k) => Some(EventType::KeyPress(k)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(WM_KEYUP) => {
|
|
||||||
let code = Self::get_virtual_key(lparam);
|
|
||||||
match Self::virtual_key_2_key(code as u16) {
|
|
||||||
Some(k) => Some(EventType::KeyRelease(k)),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_2_virtual_key(key: Key) -> Option<WORD> {
|
fn key_2_virtual_key(key: Key) -> Option<WORD> {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
use winapi::ctypes::c_int;
|
use winapi::ctypes::c_int;
|
||||||
use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM};
|
use winapi::shared::minwindef::{DWORD, HINSTANCE, LPARAM, LRESULT, WPARAM};
|
||||||
use winapi::shared::windef::HHOOK;
|
use winapi::shared::windef::HHOOK__;
|
||||||
use winapi::um::errhandlingapi::GetLastError;
|
use winapi::um::errhandlingapi::GetLastError;
|
||||||
use winapi::um::winuser::{SetWindowsHookExA, UnhookWindowsHookEx};
|
use winapi::um::winuser::{SetWindowsHookExW, UnhookWindowsHookEx};
|
||||||
|
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod mouse;
|
pub mod mouse;
|
||||||
|
|
||||||
|
@ -16,22 +16,28 @@ pub enum HookError {
|
||||||
Keyboard(DWORD),
|
Keyboard(DWORD),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn hook(id_hook: c_int, callback: HookCallback) -> Result<HHOOK, DWORD> {
|
pub unsafe fn hook(
|
||||||
let hook = SetWindowsHookExA(id_hook, Some(callback), null_mut(), 0);
|
hook_id: c_int,
|
||||||
|
hook_ptr: &AtomicPtr<HHOOK__>,
|
||||||
|
callback: HookCallback,
|
||||||
|
) -> Result<(), DWORD> {
|
||||||
|
hook_ptr.store(
|
||||||
|
SetWindowsHookExW(hook_id, Some(callback), 0 as HINSTANCE, 0),
|
||||||
|
Ordering::Relaxed,
|
||||||
|
);
|
||||||
|
|
||||||
if hook.is_null() {
|
if hook_ptr.load(Ordering::Relaxed).is_null() {
|
||||||
let error = GetLastError();
|
let error = GetLastError();
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(hook)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unhook(hook: HHOOK) -> Result<(), DWORD> {
|
pub unsafe fn unhook(hook_ptr: &AtomicPtr<HHOOK__>) -> Result<(), DWORD> {
|
||||||
if hook.is_null() {
|
if !hook_ptr.load(Ordering::Relaxed).is_null() {
|
||||||
return Ok(());
|
UnhookWindowsHookEx(hook_ptr.load(Ordering::Relaxed));
|
||||||
}
|
hook_ptr.store(null_mut(), Ordering::Relaxed);
|
||||||
|
}
|
||||||
UnhookWindowsHookEx(hook);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,39 @@
|
||||||
use crate::windows;
|
use crate::windows;
|
||||||
use crate::{Button, Event, EventType, HookCallback, Robot};
|
use crate::{Button, Event, EventType, HookCallback, Robot};
|
||||||
use std::convert::TryInto;
|
use once_cell::sync::Lazy;
|
||||||
use std::mem::{size_of, transmute};
|
use std::mem::{size_of, transmute};
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use winapi::ctypes::c_int;
|
use winapi::ctypes::c_int;
|
||||||
use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM};
|
use winapi::shared::minwindef::{DWORD, HIWORD, LPARAM, LRESULT, WPARAM};
|
||||||
use winapi::shared::windef::HHOOK;
|
use winapi::shared::windef::{HHOOK__, POINT};
|
||||||
use winapi::um::winuser::{
|
use winapi::um::winuser::{
|
||||||
CallNextHookEx, GetAsyncKeyState, GetSystemMetrics, SendInput, HC_ACTION, INPUT, INPUT_MOUSE,
|
CallNextHookEx, GetAsyncKeyState, GetCursorPos, GetSystemMetrics, SendInput, HC_ACTION, INPUT,
|
||||||
LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN,
|
INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_HWHEEL, MOUSEEVENTF_LEFTDOWN,
|
||||||
MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP,
|
MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE,
|
||||||
MOUSEEVENTF_VIRTUALDESK, MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN,
|
MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK, MOUSEEVENTF_WHEEL,
|
||||||
SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1,
|
MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN,
|
||||||
VK_XBUTTON2, WH_MOUSE_LL, WM_LBUTTONDOWN,
|
SM_YVIRTUALSCREEN, VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1, VK_XBUTTON2, WH_MOUSE_LL,
|
||||||
|
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, WM_RBUTTONDOWN,
|
||||||
|
WM_RBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP, XBUTTON1, XBUTTON2,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn default_callback(event: Event) {
|
fn default_callback(event: Event) {
|
||||||
println!("Default : Event {:?}", event);
|
println!("Default : Event {:?}", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut HOOK: HHOOK = null_mut();
|
static MOUSE_HHOOK: Lazy<AtomicPtr<HHOOK__>> = Lazy::new(AtomicPtr::default);
|
||||||
static mut HOOK_CALLBACK: HookCallback = default_callback;
|
static mut HOOK_CALLBACK: HookCallback = default_callback;
|
||||||
|
|
||||||
impl Robot {
|
impl Robot {
|
||||||
pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> {
|
pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> {
|
||||||
if HOOK.is_null() {
|
if MOUSE_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||||
let r = windows::hook(WH_MOUSE_LL, Self::mouse_raw_callback);
|
let r = windows::hook(WH_MOUSE_LL, &*MOUSE_HHOOK, Self::mouse_raw_callback);
|
||||||
|
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
return Err(windows::HookError::Mouse(r.err().unwrap()));
|
return Err(windows::HookError::Mouse(r.err().unwrap()));
|
||||||
}
|
}
|
||||||
HOOK = r.ok().unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOK_CALLBACK = callback;
|
HOOK_CALLBACK = callback;
|
||||||
|
@ -40,12 +42,11 @@ impl Robot {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mouse_unlisten() -> Result<(), windows::HookError> {
|
pub unsafe fn mouse_unlisten() -> Result<(), windows::HookError> {
|
||||||
if !HOOK.is_null() {
|
if !MOUSE_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||||
let r = windows::unhook(HOOK);
|
let r = windows::unhook(&*MOUSE_HHOOK);
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
return Err(windows::HookError::Mouse(r.err().unwrap()));
|
return Err(windows::HookError::Mouse(r.err().unwrap()));
|
||||||
}
|
}
|
||||||
HOOK = null_mut();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOK_CALLBACK = default_callback;
|
HOOK_CALLBACK = default_callback;
|
||||||
|
@ -53,6 +54,17 @@ impl Robot {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mouse_location() -> (i32, i32) {
|
||||||
|
let mut point = POINT { x: 0, y: 0 };
|
||||||
|
let result = unsafe { GetCursorPos(&mut point) };
|
||||||
|
|
||||||
|
if result != 0 {
|
||||||
|
(point.x, point.y)
|
||||||
|
} else {
|
||||||
|
(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mouse_move_to(dx: i32, dy: i32) {
|
pub fn mouse_move_to(dx: i32, dy: i32) {
|
||||||
let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) };
|
let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) };
|
||||||
let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) };
|
let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) };
|
||||||
|
@ -74,24 +86,14 @@ impl Robot {
|
||||||
dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN;
|
dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut input = INPUT {
|
Self::mouse_event(
|
||||||
type_: INPUT_MOUSE,
|
(dx - unsafe { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535
|
||||||
u: unsafe {
|
/ unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) },
|
||||||
transmute(MOUSEINPUT {
|
(dy - unsafe { GetSystemMetrics(SM_YVIRTUALSCREEN) }) * 65535
|
||||||
dx: (dx - { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 / {
|
/ unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) },
|
||||||
GetSystemMetrics(SM_CXVIRTUALSCREEN)
|
0,
|
||||||
},
|
dw_flags,
|
||||||
dy: (dy - { GetSystemMetrics(SM_YVIRTUALSCREEN) }) * 65535 / {
|
);
|
||||||
GetSystemMetrics(SM_CYVIRTUALSCREEN)
|
|
||||||
},
|
|
||||||
mouseData: 0,
|
|
||||||
dwFlags: dw_flags,
|
|
||||||
time: 0,
|
|
||||||
dwExtraInfo: 0,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
|
||||||
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_press(button: Button) {
|
pub fn mouse_press(button: Button) {
|
||||||
|
@ -99,20 +101,7 @@ impl Robot {
|
||||||
|
|
||||||
let dw_flags = btn;
|
let dw_flags = btn;
|
||||||
|
|
||||||
let mut input = INPUT {
|
Self::mouse_event(0, 0, 0, dw_flags);
|
||||||
type_: INPUT_MOUSE,
|
|
||||||
u: unsafe {
|
|
||||||
transmute(MOUSEINPUT {
|
|
||||||
dx: 0,
|
|
||||||
dy: 0,
|
|
||||||
mouseData: 0,
|
|
||||||
dwFlags: dw_flags,
|
|
||||||
time: 0,
|
|
||||||
dwExtraInfo: 0,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
|
||||||
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_release(button: Button) {
|
pub fn mouse_release(button: Button) {
|
||||||
|
@ -120,13 +109,31 @@ impl Robot {
|
||||||
|
|
||||||
let dw_flags = btn;
|
let dw_flags = btn;
|
||||||
|
|
||||||
|
Self::mouse_event(0, 0, 0, dw_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mouse_pressed(button: Button) -> bool {
|
||||||
|
(unsafe { GetAsyncKeyState(Self::mouse_button_virtual_key(button)) } >> 15) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mouse_wheel_x(length: i32) {
|
||||||
|
let dw_flags = MOUSEEVENTF_HWHEEL;
|
||||||
|
Self::mouse_event(0, 0, unsafe { transmute(length * 120) }, dw_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mouse_wheel_y(length: i32) {
|
||||||
|
let dw_flags = MOUSEEVENTF_WHEEL;
|
||||||
|
Self::mouse_event(0, 0, unsafe { transmute(length * 120) }, dw_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_event(dx: i32, dy: i32, mouse_data: u32, dw_flags: u32) {
|
||||||
let mut input = INPUT {
|
let mut input = INPUT {
|
||||||
type_: INPUT_MOUSE,
|
type_: INPUT_MOUSE,
|
||||||
u: unsafe {
|
u: unsafe {
|
||||||
transmute(MOUSEINPUT {
|
transmute(MOUSEINPUT {
|
||||||
dx: 0,
|
dx,
|
||||||
dy: 0,
|
dy,
|
||||||
mouseData: 0,
|
mouseData: mouse_data,
|
||||||
dwFlags: dw_flags,
|
dwFlags: dw_flags,
|
||||||
time: 0,
|
time: 0,
|
||||||
dwExtraInfo: 0,
|
dwExtraInfo: 0,
|
||||||
|
@ -136,10 +143,6 @@ impl Robot {
|
||||||
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_pressed(button: Button) -> bool {
|
|
||||||
(unsafe { GetAsyncKeyState(Self::mouse_button_virtual_key(button)) } >> 15) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mouse_button_event(ev: EventType) -> DWORD {
|
fn mouse_button_event(ev: EventType) -> DWORD {
|
||||||
match ev {
|
match ev {
|
||||||
EventType::MousePress(button) => match button {
|
EventType::MousePress(button) => match button {
|
||||||
|
@ -174,13 +177,47 @@ impl Robot {
|
||||||
(mouse.pt.x, mouse.pt.y)
|
(mouse.pt.x, mouse.pt.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
unsafe extern "system" fn mouse_raw_callback(
|
unsafe extern "system" fn mouse_raw_callback(
|
||||||
code: c_int,
|
code: c_int,
|
||||||
param: WPARAM,
|
w_param: WPARAM,
|
||||||
lpdata: LPARAM,
|
l_param: LPARAM,
|
||||||
) -> LRESULT {
|
) -> LRESULT {
|
||||||
if code == HC_ACTION {
|
if code == HC_ACTION {
|
||||||
let opt = Self::mouse_convert(param, lpdata);
|
let opt = match w_param as u32 {
|
||||||
|
WM_LBUTTONDOWN => Some(EventType::MousePress(Button::Left)),
|
||||||
|
WM_LBUTTONUP => Some(EventType::MouseRelease(Button::Left)),
|
||||||
|
WM_MBUTTONDOWN => Some(EventType::MousePress(Button::Middle)),
|
||||||
|
WM_MBUTTONUP => Some(EventType::MouseRelease(Button::Middle)),
|
||||||
|
WM_RBUTTONDOWN => Some(EventType::MousePress(Button::Right)),
|
||||||
|
WM_RBUTTONUP => Some(EventType::MouseRelease(Button::Right)),
|
||||||
|
WM_XBUTTONDOWN => {
|
||||||
|
let llhs = &*(l_param as *const MSLLHOOKSTRUCT);
|
||||||
|
|
||||||
|
match HIWORD(llhs.mouseData) {
|
||||||
|
XBUTTON1 => Some(EventType::MousePress(Button::X1)),
|
||||||
|
XBUTTON2 => Some(EventType::MousePress(Button::X2)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WM_XBUTTONUP => {
|
||||||
|
let llhs = &*(l_param as *const MSLLHOOKSTRUCT);
|
||||||
|
|
||||||
|
match HIWORD(llhs.mouseData) {
|
||||||
|
XBUTTON1 => Some(EventType::MouseRelease(Button::X1)),
|
||||||
|
XBUTTON2 => Some(EventType::MouseRelease(Button::X2)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WM_MOUSEMOVE => {
|
||||||
|
let (x, y) = Self::get_mouse_point(l_param);
|
||||||
|
Some(EventType::MouseMoveTo {
|
||||||
|
x: x as f64,
|
||||||
|
y: y as f64,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
if let Some(event_type) = opt {
|
if let Some(event_type) = opt {
|
||||||
let event = Event {
|
let event = Event {
|
||||||
event_type,
|
event_type,
|
||||||
|
@ -189,25 +226,6 @@ impl Robot {
|
||||||
HOOK_CALLBACK(event);
|
HOOK_CALLBACK(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallNextHookEx(HOOK, code, param, lpdata)
|
CallNextHookEx(null_mut(), code, w_param, l_param)
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn mouse_convert(wparam: WPARAM, lparam: LPARAM) -> Option<EventType> {
|
|
||||||
match wparam.try_into() {
|
|
||||||
Ok(WM_LBUTTONDOWN) => Some(EventType::MousePress(Button::Left)),
|
|
||||||
Ok(WM_LBUTTONUP) => Some(EventType::MouseRelease(Button::Left)),
|
|
||||||
Ok(WM_MBUTTONDOWN) => Some(EventType::MousePress(Button::Middle)),
|
|
||||||
Ok(WM_MBUTTONUP) => Some(EventType::MouseRelease(Button::Middle)),
|
|
||||||
Ok(WM_RBUTTONDOWN) => Some(EventType::MousePress(Button::Right)),
|
|
||||||
Ok(WM_RBUTTONUP) => Some(EventType::MouseRelease(Button::Right)),
|
|
||||||
Ok(WM_MOUSEMOVE) => {
|
|
||||||
let (x, y) = Self::get_mouse_point(lparam);
|
|
||||||
Some(EventType::MouseMoveTo {
|
|
||||||
x: x as f64,
|
|
||||||
y: y as f64,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user