update
This commit is contained in:
parent
ea09dc582d
commit
33d06b9cf8
|
@ -9,7 +9,7 @@ edition = "2018"
|
|||
[dependencies]
|
||||
serde = { 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]
|
||||
with_serde = ["serde", "serde_derive"]
|
||||
|
|
|
@ -1,280 +1,277 @@
|
|||
use crate::windows;
|
||||
use crate::{Event, EventType, HookCallback, Key, Robot};
|
||||
use lazy_static::lazy_static;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::mem::{size_of, transmute_copy};
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
use std::time::SystemTime;
|
||||
use winapi::ctypes::c_int;
|
||||
use winapi::shared::minwindef::{LPARAM, LRESULT, WORD, WPARAM};
|
||||
use winapi::shared::windef::HHOOK;
|
||||
use winapi::shared::windef::HHOOK__;
|
||||
use winapi::um::winuser::{
|
||||
CallNextHookEx, GetAsyncKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT, INPUT_KEYBOARD,
|
||||
KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT, WH_KEYBOARD_LL,
|
||||
WM_KEYDOWN, WM_KEYUP,
|
||||
CallNextHookEx, GetAsyncKeyState, GetKeyState, MapVirtualKeyW, SendInput, HC_ACTION, INPUT,
|
||||
INPUT_KEYBOARD, KBDLLHOOKSTRUCT, KEYBDINPUT, KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, LPINPUT,
|
||||
WH_KEYBOARD_LL, WM_KEYDOWN, WM_KEYUP,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
static ref KEY_2_VK_MAP: HashMap<Key, WORD> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(Key::Digit0 , 0x30);
|
||||
m.insert(Key::Digit1 , 0x31);
|
||||
m.insert(Key::Digit2 , 0x32);
|
||||
m.insert(Key::Digit3 , 0x33);
|
||||
m.insert(Key::Digit4 , 0x34);
|
||||
m.insert(Key::Digit5 , 0x35);
|
||||
m.insert(Key::Digit6 , 0x36);
|
||||
m.insert(Key::Digit7 , 0x37);
|
||||
m.insert(Key::Digit8 , 0x38);
|
||||
m.insert(Key::Digit9 , 0x39);
|
||||
m.insert(Key::KeyA , 0x41);
|
||||
m.insert(Key::KeyB , 0x42);
|
||||
m.insert(Key::KeyC , 0x43);
|
||||
m.insert(Key::KeyD , 0x44);
|
||||
m.insert(Key::KeyE , 0x45);
|
||||
m.insert(Key::KeyF , 0x46);
|
||||
m.insert(Key::KeyG , 0x47);
|
||||
m.insert(Key::KeyH , 0x48);
|
||||
m.insert(Key::KeyI , 0x49);
|
||||
m.insert(Key::KeyJ , 0x4A);
|
||||
m.insert(Key::KeyK , 0x4B);
|
||||
m.insert(Key::KeyL , 0x4C);
|
||||
m.insert(Key::KeyM , 0x4D);
|
||||
m.insert(Key::KeyN , 0x4E);
|
||||
m.insert(Key::KeyO , 0x4F);
|
||||
m.insert(Key::KeyP , 0x50);
|
||||
m.insert(Key::KeyQ , 0x51);
|
||||
m.insert(Key::KeyR , 0x52);
|
||||
m.insert(Key::KeyS , 0x53);
|
||||
m.insert(Key::KeyT , 0x54);
|
||||
m.insert(Key::KeyU , 0x55);
|
||||
m.insert(Key::KeyV , 0x56);
|
||||
m.insert(Key::KeyW , 0x57);
|
||||
m.insert(Key::KeyX , 0x58);
|
||||
m.insert(Key::KeyY , 0x59);
|
||||
m.insert(Key::KeyZ , 0x5A);
|
||||
m.insert(Key::F1 , 0x70);
|
||||
m.insert(Key::F2 , 0x71);
|
||||
m.insert(Key::F3 , 0x72);
|
||||
m.insert(Key::F4 , 0x73);
|
||||
m.insert(Key::F5 , 0x74);
|
||||
m.insert(Key::F6 , 0x75);
|
||||
m.insert(Key::F7 , 0x76);
|
||||
m.insert(Key::F8 , 0x77);
|
||||
m.insert(Key::F9 , 0x78);
|
||||
m.insert(Key::F10 , 0x79);
|
||||
m.insert(Key::F11 , 0x7A);
|
||||
m.insert(Key::F12 , 0x7B);
|
||||
m.insert(Key::F13 , 0x7C);
|
||||
m.insert(Key::F14 , 0x7D);
|
||||
m.insert(Key::F15 , 0x7E);
|
||||
m.insert(Key::F16 , 0x7F);
|
||||
m.insert(Key::F17 , 0x80);
|
||||
m.insert(Key::F18 , 0x81);
|
||||
m.insert(Key::F19 , 0x82);
|
||||
m.insert(Key::F20 , 0x83);
|
||||
m.insert(Key::F21 , 0x84);
|
||||
m.insert(Key::F22 , 0x85);
|
||||
m.insert(Key::F23 , 0x86);
|
||||
m.insert(Key::F24 , 0x87);
|
||||
m.insert(Key::Numpad0 , 0x60);
|
||||
m.insert(Key::Numpad1 , 0x61);
|
||||
m.insert(Key::Numpad2 , 0x62);
|
||||
m.insert(Key::Numpad3 , 0x63);
|
||||
m.insert(Key::Numpad4 , 0x64);
|
||||
m.insert(Key::Numpad5 , 0x65);
|
||||
m.insert(Key::Numpad6 , 0x66);
|
||||
m.insert(Key::Numpad7 , 0x67);
|
||||
m.insert(Key::Numpad8 , 0x68);
|
||||
m.insert(Key::Numpad9 , 0x69);
|
||||
m.insert(Key::NumpadAdd , 0x6B); // Add
|
||||
m.insert(Key::NumpadSubtract , 0x6D); // Subtract
|
||||
m.insert(Key::NumpadMultiply , 0x6A); // Multiply
|
||||
m.insert(Key::NumpadDivide , 0x6F); // Divide
|
||||
m.insert(Key::NumpadDecimal , 0x6E); // Decimal
|
||||
m.insert(Key::NumpadEqual , '=' as u16);
|
||||
m.insert(Key::NumpadComma , ',' as u16);
|
||||
m.insert(Key::NumpadEnter , 0x0D);
|
||||
m.insert(Key::NumLock , 0x90);
|
||||
m.insert(Key::Minus , '-' as u16);
|
||||
m.insert(Key::Equal , '=' as u16);
|
||||
m.insert(Key::BracketLeft , '{' as u16);
|
||||
m.insert(Key::BracketRight , '}' as u16);
|
||||
m.insert(Key::Semicolon , ';' as u16);
|
||||
m.insert(Key::Quote , '\'' as u16);
|
||||
m.insert(Key::Backquote , '`' as u16);
|
||||
m.insert(Key::Backslash , '\\' as u16);
|
||||
m.insert(Key::Comma , ',' as u16);
|
||||
m.insert(Key::Period , '~' as u16);
|
||||
m.insert(Key::Slash , '/' as u16);
|
||||
m.insert(Key::Escape , 0x1B);
|
||||
m.insert(Key::Enter , 0x0D);
|
||||
m.insert(Key::Backspace , 0x08);
|
||||
m.insert(Key::Tab , 0x09);
|
||||
m.insert(Key::Space , 0x20);
|
||||
m.insert(Key::CapsLock , 0x14);
|
||||
m.insert(Key::ShiftLeft , 0xA0);
|
||||
m.insert(Key::ShiftRight , 0xA1);
|
||||
m.insert(Key::ControlLeft , 0xA2);
|
||||
m.insert(Key::ControlRight , 0xA3);
|
||||
m.insert(Key::AltLeft , 0xA4);
|
||||
m.insert(Key::AltRight , 0xA5);
|
||||
m.insert(Key::Pause , 0x13);
|
||||
m.insert(Key::ScrollLock , 0x91);
|
||||
m.insert(Key::PrintScreen , 0x2C);
|
||||
m.insert(Key::ArrowLeft , 0x25);
|
||||
m.insert(Key::ArrowUp , 0x26);
|
||||
m.insert(Key::ArrowRight , 0x27);
|
||||
m.insert(Key::ArrowDown , 0x28);
|
||||
m.insert(Key::PageUp , 0x21);
|
||||
m.insert(Key::PageDown , 0x22);
|
||||
m.insert(Key::Home , 0x24);
|
||||
m.insert(Key::End , 0x23);
|
||||
m.insert(Key::Insert , 0x2D);
|
||||
m.insert(Key::Delete , 0x2E);
|
||||
m.insert(Key::MetaLeft , 0x5B);
|
||||
m.insert(Key::MetaRight , 0x5C);
|
||||
m
|
||||
};
|
||||
static KEY_2_VK_MAP: Lazy<HashMap<Key, WORD>> = Lazy::new(|| {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(Key::Digit0, 0x30);
|
||||
m.insert(Key::Digit1, 0x31);
|
||||
m.insert(Key::Digit2, 0x32);
|
||||
m.insert(Key::Digit3, 0x33);
|
||||
m.insert(Key::Digit4, 0x34);
|
||||
m.insert(Key::Digit5, 0x35);
|
||||
m.insert(Key::Digit6, 0x36);
|
||||
m.insert(Key::Digit7, 0x37);
|
||||
m.insert(Key::Digit8, 0x38);
|
||||
m.insert(Key::Digit9, 0x39);
|
||||
m.insert(Key::KeyA, 0x41);
|
||||
m.insert(Key::KeyB, 0x42);
|
||||
m.insert(Key::KeyC, 0x43);
|
||||
m.insert(Key::KeyD, 0x44);
|
||||
m.insert(Key::KeyE, 0x45);
|
||||
m.insert(Key::KeyF, 0x46);
|
||||
m.insert(Key::KeyG, 0x47);
|
||||
m.insert(Key::KeyH, 0x48);
|
||||
m.insert(Key::KeyI, 0x49);
|
||||
m.insert(Key::KeyJ, 0x4A);
|
||||
m.insert(Key::KeyK, 0x4B);
|
||||
m.insert(Key::KeyL, 0x4C);
|
||||
m.insert(Key::KeyM, 0x4D);
|
||||
m.insert(Key::KeyN, 0x4E);
|
||||
m.insert(Key::KeyO, 0x4F);
|
||||
m.insert(Key::KeyP, 0x50);
|
||||
m.insert(Key::KeyQ, 0x51);
|
||||
m.insert(Key::KeyR, 0x52);
|
||||
m.insert(Key::KeyS, 0x53);
|
||||
m.insert(Key::KeyT, 0x54);
|
||||
m.insert(Key::KeyU, 0x55);
|
||||
m.insert(Key::KeyV, 0x56);
|
||||
m.insert(Key::KeyW, 0x57);
|
||||
m.insert(Key::KeyX, 0x58);
|
||||
m.insert(Key::KeyY, 0x59);
|
||||
m.insert(Key::KeyZ, 0x5A);
|
||||
m.insert(Key::F1, 0x70);
|
||||
m.insert(Key::F2, 0x71);
|
||||
m.insert(Key::F3, 0x72);
|
||||
m.insert(Key::F4, 0x73);
|
||||
m.insert(Key::F5, 0x74);
|
||||
m.insert(Key::F6, 0x75);
|
||||
m.insert(Key::F7, 0x76);
|
||||
m.insert(Key::F8, 0x77);
|
||||
m.insert(Key::F9, 0x78);
|
||||
m.insert(Key::F10, 0x79);
|
||||
m.insert(Key::F11, 0x7A);
|
||||
m.insert(Key::F12, 0x7B);
|
||||
m.insert(Key::F13, 0x7C);
|
||||
m.insert(Key::F14, 0x7D);
|
||||
m.insert(Key::F15, 0x7E);
|
||||
m.insert(Key::F16, 0x7F);
|
||||
m.insert(Key::F17, 0x80);
|
||||
m.insert(Key::F18, 0x81);
|
||||
m.insert(Key::F19, 0x82);
|
||||
m.insert(Key::F20, 0x83);
|
||||
m.insert(Key::F21, 0x84);
|
||||
m.insert(Key::F22, 0x85);
|
||||
m.insert(Key::F23, 0x86);
|
||||
m.insert(Key::F24, 0x87);
|
||||
m.insert(Key::Numpad0, 0x60);
|
||||
m.insert(Key::Numpad1, 0x61);
|
||||
m.insert(Key::Numpad2, 0x62);
|
||||
m.insert(Key::Numpad3, 0x63);
|
||||
m.insert(Key::Numpad4, 0x64);
|
||||
m.insert(Key::Numpad5, 0x65);
|
||||
m.insert(Key::Numpad6, 0x66);
|
||||
m.insert(Key::Numpad7, 0x67);
|
||||
m.insert(Key::Numpad8, 0x68);
|
||||
m.insert(Key::Numpad9, 0x69);
|
||||
m.insert(Key::NumpadAdd, 0x6B); // Add
|
||||
m.insert(Key::NumpadSubtract, 0x6D); // Subtract
|
||||
m.insert(Key::NumpadMultiply, 0x6A); // Multiply
|
||||
m.insert(Key::NumpadDivide, 0x6F); // Divide
|
||||
m.insert(Key::NumpadDecimal, 0x6E); // Decimal
|
||||
m.insert(Key::NumpadEqual, '=' as u16);
|
||||
m.insert(Key::NumpadComma, ',' as u16);
|
||||
m.insert(Key::NumpadEnter, 0x0D);
|
||||
m.insert(Key::NumLock, 0x90);
|
||||
m.insert(Key::Minus, '-' as u16);
|
||||
m.insert(Key::Equal, '=' as u16);
|
||||
m.insert(Key::BracketLeft, '{' as u16);
|
||||
m.insert(Key::BracketRight, '}' as u16);
|
||||
m.insert(Key::Semicolon, ';' as u16);
|
||||
m.insert(Key::Quote, '\'' as u16);
|
||||
m.insert(Key::Backquote, '`' as u16);
|
||||
m.insert(Key::Backslash, '\\' as u16);
|
||||
m.insert(Key::Comma, ',' as u16);
|
||||
m.insert(Key::Period, '~' as u16);
|
||||
m.insert(Key::Slash, '/' as u16);
|
||||
m.insert(Key::Escape, 0x1B);
|
||||
m.insert(Key::Enter, 0x0D);
|
||||
m.insert(Key::Backspace, 0x08);
|
||||
m.insert(Key::Tab, 0x09);
|
||||
m.insert(Key::Space, 0x20);
|
||||
m.insert(Key::CapsLock, 0x14);
|
||||
m.insert(Key::ShiftLeft, 0xA0);
|
||||
m.insert(Key::ShiftRight, 0xA1);
|
||||
m.insert(Key::ControlLeft, 0xA2);
|
||||
m.insert(Key::ControlRight, 0xA3);
|
||||
m.insert(Key::AltLeft, 0xA4);
|
||||
m.insert(Key::AltRight, 0xA5);
|
||||
m.insert(Key::Pause, 0x13);
|
||||
m.insert(Key::ScrollLock, 0x91);
|
||||
m.insert(Key::PrintScreen, 0x2C);
|
||||
m.insert(Key::ArrowLeft, 0x25);
|
||||
m.insert(Key::ArrowUp, 0x26);
|
||||
m.insert(Key::ArrowRight, 0x27);
|
||||
m.insert(Key::ArrowDown, 0x28);
|
||||
m.insert(Key::PageUp, 0x21);
|
||||
m.insert(Key::PageDown, 0x22);
|
||||
m.insert(Key::Home, 0x24);
|
||||
m.insert(Key::End, 0x23);
|
||||
m.insert(Key::Insert, 0x2D);
|
||||
m.insert(Key::Delete, 0x2E);
|
||||
m.insert(Key::MetaLeft, 0x5B);
|
||||
m.insert(Key::MetaRight, 0x5C);
|
||||
m
|
||||
});
|
||||
|
||||
static ref VK_2_KEY_MAP: HashMap<WORD, Key> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(0x30, Key::Digit0);
|
||||
m.insert(0x31, Key::Digit1);
|
||||
m.insert(0x32, Key::Digit2);
|
||||
m.insert(0x33, Key::Digit3);
|
||||
m.insert(0x34, Key::Digit4);
|
||||
m.insert(0x35, Key::Digit5);
|
||||
m.insert(0x36, Key::Digit6);
|
||||
m.insert(0x37, Key::Digit7);
|
||||
m.insert(0x38, Key::Digit8);
|
||||
m.insert(0x39, Key::Digit9);
|
||||
m.insert(0x41, Key::KeyA);
|
||||
m.insert(0x42, Key::KeyB);
|
||||
m.insert(0x43, Key::KeyC);
|
||||
m.insert(0x44, Key::KeyD);
|
||||
m.insert(0x45, Key::KeyE);
|
||||
m.insert(0x46, Key::KeyF);
|
||||
m.insert(0x47, Key::KeyG);
|
||||
m.insert(0x48, Key::KeyH);
|
||||
m.insert(0x49, Key::KeyI);
|
||||
m.insert(0x4A, Key::KeyJ);
|
||||
m.insert(0x4B, Key::KeyK);
|
||||
m.insert(0x4C, Key::KeyL);
|
||||
m.insert(0x4D, Key::KeyM);
|
||||
m.insert(0x4E, Key::KeyN);
|
||||
m.insert(0x4F, Key::KeyO);
|
||||
m.insert(0x50, Key::KeyP);
|
||||
m.insert(0x51, Key::KeyQ);
|
||||
m.insert(0x52, Key::KeyR);
|
||||
m.insert(0x53, Key::KeyS);
|
||||
m.insert(0x54, Key::KeyT);
|
||||
m.insert(0x55, Key::KeyU);
|
||||
m.insert(0x56, Key::KeyV);
|
||||
m.insert(0x57, Key::KeyW);
|
||||
m.insert(0x58, Key::KeyX);
|
||||
m.insert(0x59, Key::KeyY);
|
||||
m.insert(0x5A, Key::KeyZ);
|
||||
m.insert(0x70, Key::F1);
|
||||
m.insert(0x71, Key::F2);
|
||||
m.insert(0x72, Key::F3);
|
||||
m.insert(0x73, Key::F4);
|
||||
m.insert(0x74, Key::F5);
|
||||
m.insert(0x75, Key::F6);
|
||||
m.insert(0x76, Key::F7);
|
||||
m.insert(0x77, Key::F8);
|
||||
m.insert(0x78, Key::F9);
|
||||
m.insert(0x79, Key::F10);
|
||||
m.insert(0x7A, Key::F11);
|
||||
m.insert(0x7B, Key::F12);
|
||||
m.insert(0x7C, Key::F13);
|
||||
m.insert(0x7D, Key::F14);
|
||||
m.insert(0x7E, Key::F15);
|
||||
m.insert(0x7F, Key::F16);
|
||||
m.insert(0x80, Key::F17);
|
||||
m.insert(0x81, Key::F18);
|
||||
m.insert(0x82, Key::F19);
|
||||
m.insert(0x83, Key::F20);
|
||||
m.insert(0x84, Key::F21);
|
||||
m.insert(0x85, Key::F22);
|
||||
m.insert(0x86, Key::F23);
|
||||
m.insert(0x87, Key::F24);
|
||||
m.insert(0x60, Key::Numpad0);
|
||||
m.insert(0x61, Key::Numpad1);
|
||||
m.insert(0x62, Key::Numpad2);
|
||||
m.insert(0x63, Key::Numpad3);
|
||||
m.insert(0x64, Key::Numpad4);
|
||||
m.insert(0x65, Key::Numpad5);
|
||||
m.insert(0x66, Key::Numpad6);
|
||||
m.insert(0x67, Key::Numpad7);
|
||||
m.insert(0x68, Key::Numpad8);
|
||||
m.insert(0x69, Key::Numpad9);
|
||||
m.insert(0x6B, Key::NumpadAdd); // Add
|
||||
m.insert(0x6D, Key::NumpadSubtract); // Subtract
|
||||
m.insert(0x6A, Key::NumpadMultiply); // Multiply
|
||||
m.insert(0x6F, Key::NumpadDivide); // Divide
|
||||
m.insert(0x6E, Key::NumpadDecimal); // Decimal
|
||||
m.insert( 0x0D, Key::NumpadEnter);
|
||||
m.insert( 0x90, Key::NumLock);
|
||||
m.insert('-' as u16, Key::Minus);
|
||||
m.insert('=' as u16, Key::Equal);
|
||||
m.insert('{' as u16, Key::BracketLeft);
|
||||
m.insert('}' as u16, Key::BracketRight);
|
||||
m.insert(';' as u16, Key::Semicolon);
|
||||
m.insert('\'' as u16, Key::Quote);
|
||||
m.insert('`' as u16, Key::Backquote);
|
||||
m.insert('\\' as u16, Key::Backslash);
|
||||
m.insert(',' as u16, Key::Comma);
|
||||
m.insert('~' as u16, Key::Period);
|
||||
m.insert('/' as u16, Key::Slash);
|
||||
m.insert(0x1B, Key::Escape);
|
||||
m.insert( 0x0D, Key::Enter);
|
||||
m.insert( 0x08, Key::Backspace);
|
||||
m.insert( 0x09, Key::Tab);
|
||||
m.insert( 0x20, Key::Space);
|
||||
m.insert(0x14, Key::CapsLock);
|
||||
m.insert(0xA0, Key::ShiftLeft);
|
||||
m.insert(0xA1, Key::ShiftRight);
|
||||
m.insert( 0xA2, Key::ControlLeft);
|
||||
m.insert( 0xA3, Key::ControlRight);
|
||||
m.insert( 0xA4, Key::AltLeft);
|
||||
m.insert(0xA5, Key::AltRight);
|
||||
m.insert(0x13, Key::Pause);
|
||||
m.insert(0x91, Key::ScrollLock);
|
||||
m.insert(0x2C, Key::PrintScreen);
|
||||
m.insert(0x25, Key::ArrowLeft);
|
||||
m.insert(0x26, Key::ArrowUp);
|
||||
m.insert(0x27, Key::ArrowRight);
|
||||
m.insert(0x28, Key::ArrowDown);
|
||||
m.insert(0x21, Key::PageUp);
|
||||
m.insert(0x22, Key::PageDown);
|
||||
m.insert( 0x24, Key::Home);
|
||||
m.insert( 0x23, Key::End);
|
||||
m.insert(0x2D, Key::Insert);
|
||||
m.insert(0x2E, Key::Delete);
|
||||
m.insert(0x5B, Key::MetaLeft);
|
||||
m.insert(0x5C, Key::MetaRight);
|
||||
m
|
||||
};
|
||||
}
|
||||
static VK_2_KEY_MAP: Lazy<HashMap<WORD, Key>> = Lazy::new(|| {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(0x30, Key::Digit0);
|
||||
m.insert(0x31, Key::Digit1);
|
||||
m.insert(0x32, Key::Digit2);
|
||||
m.insert(0x33, Key::Digit3);
|
||||
m.insert(0x34, Key::Digit4);
|
||||
m.insert(0x35, Key::Digit5);
|
||||
m.insert(0x36, Key::Digit6);
|
||||
m.insert(0x37, Key::Digit7);
|
||||
m.insert(0x38, Key::Digit8);
|
||||
m.insert(0x39, Key::Digit9);
|
||||
m.insert(0x41, Key::KeyA);
|
||||
m.insert(0x42, Key::KeyB);
|
||||
m.insert(0x43, Key::KeyC);
|
||||
m.insert(0x44, Key::KeyD);
|
||||
m.insert(0x45, Key::KeyE);
|
||||
m.insert(0x46, Key::KeyF);
|
||||
m.insert(0x47, Key::KeyG);
|
||||
m.insert(0x48, Key::KeyH);
|
||||
m.insert(0x49, Key::KeyI);
|
||||
m.insert(0x4A, Key::KeyJ);
|
||||
m.insert(0x4B, Key::KeyK);
|
||||
m.insert(0x4C, Key::KeyL);
|
||||
m.insert(0x4D, Key::KeyM);
|
||||
m.insert(0x4E, Key::KeyN);
|
||||
m.insert(0x4F, Key::KeyO);
|
||||
m.insert(0x50, Key::KeyP);
|
||||
m.insert(0x51, Key::KeyQ);
|
||||
m.insert(0x52, Key::KeyR);
|
||||
m.insert(0x53, Key::KeyS);
|
||||
m.insert(0x54, Key::KeyT);
|
||||
m.insert(0x55, Key::KeyU);
|
||||
m.insert(0x56, Key::KeyV);
|
||||
m.insert(0x57, Key::KeyW);
|
||||
m.insert(0x58, Key::KeyX);
|
||||
m.insert(0x59, Key::KeyY);
|
||||
m.insert(0x5A, Key::KeyZ);
|
||||
m.insert(0x70, Key::F1);
|
||||
m.insert(0x71, Key::F2);
|
||||
m.insert(0x72, Key::F3);
|
||||
m.insert(0x73, Key::F4);
|
||||
m.insert(0x74, Key::F5);
|
||||
m.insert(0x75, Key::F6);
|
||||
m.insert(0x76, Key::F7);
|
||||
m.insert(0x77, Key::F8);
|
||||
m.insert(0x78, Key::F9);
|
||||
m.insert(0x79, Key::F10);
|
||||
m.insert(0x7A, Key::F11);
|
||||
m.insert(0x7B, Key::F12);
|
||||
m.insert(0x7C, Key::F13);
|
||||
m.insert(0x7D, Key::F14);
|
||||
m.insert(0x7E, Key::F15);
|
||||
m.insert(0x7F, Key::F16);
|
||||
m.insert(0x80, Key::F17);
|
||||
m.insert(0x81, Key::F18);
|
||||
m.insert(0x82, Key::F19);
|
||||
m.insert(0x83, Key::F20);
|
||||
m.insert(0x84, Key::F21);
|
||||
m.insert(0x85, Key::F22);
|
||||
m.insert(0x86, Key::F23);
|
||||
m.insert(0x87, Key::F24);
|
||||
m.insert(0x60, Key::Numpad0);
|
||||
m.insert(0x61, Key::Numpad1);
|
||||
m.insert(0x62, Key::Numpad2);
|
||||
m.insert(0x63, Key::Numpad3);
|
||||
m.insert(0x64, Key::Numpad4);
|
||||
m.insert(0x65, Key::Numpad5);
|
||||
m.insert(0x66, Key::Numpad6);
|
||||
m.insert(0x67, Key::Numpad7);
|
||||
m.insert(0x68, Key::Numpad8);
|
||||
m.insert(0x69, Key::Numpad9);
|
||||
m.insert(0x6B, Key::NumpadAdd); // Add
|
||||
m.insert(0x6D, Key::NumpadSubtract); // Subtract
|
||||
m.insert(0x6A, Key::NumpadMultiply); // Multiply
|
||||
m.insert(0x6F, Key::NumpadDivide); // Divide
|
||||
m.insert(0x6E, Key::NumpadDecimal); // Decimal
|
||||
m.insert(0x0D, Key::NumpadEnter);
|
||||
m.insert(0x90, Key::NumLock);
|
||||
m.insert('-' as u16, Key::Minus);
|
||||
m.insert('=' as u16, Key::Equal);
|
||||
m.insert('{' as u16, Key::BracketLeft);
|
||||
m.insert('}' as u16, Key::BracketRight);
|
||||
m.insert(';' as u16, Key::Semicolon);
|
||||
m.insert('\'' as u16, Key::Quote);
|
||||
m.insert('`' as u16, Key::Backquote);
|
||||
m.insert('\\' as u16, Key::Backslash);
|
||||
m.insert(',' as u16, Key::Comma);
|
||||
m.insert('~' as u16, Key::Period);
|
||||
m.insert('/' as u16, Key::Slash);
|
||||
m.insert(0x1B, Key::Escape);
|
||||
m.insert(0x0D, Key::Enter);
|
||||
m.insert(0x08, Key::Backspace);
|
||||
m.insert(0x09, Key::Tab);
|
||||
m.insert(0x20, Key::Space);
|
||||
m.insert(0x14, Key::CapsLock);
|
||||
m.insert(0xA0, Key::ShiftLeft);
|
||||
m.insert(0xA1, Key::ShiftRight);
|
||||
m.insert(0xA2, Key::ControlLeft);
|
||||
m.insert(0xA3, Key::ControlRight);
|
||||
m.insert(0xA4, Key::AltLeft);
|
||||
m.insert(0xA5, Key::AltRight);
|
||||
m.insert(0x13, Key::Pause);
|
||||
m.insert(0x91, Key::ScrollLock);
|
||||
m.insert(0x2C, Key::PrintScreen);
|
||||
m.insert(0x25, Key::ArrowLeft);
|
||||
m.insert(0x26, Key::ArrowUp);
|
||||
m.insert(0x27, Key::ArrowRight);
|
||||
m.insert(0x28, Key::ArrowDown);
|
||||
m.insert(0x21, Key::PageUp);
|
||||
m.insert(0x22, Key::PageDown);
|
||||
m.insert(0x24, Key::Home);
|
||||
m.insert(0x23, Key::End);
|
||||
m.insert(0x2D, Key::Insert);
|
||||
m.insert(0x2E, Key::Delete);
|
||||
m.insert(0x5B, Key::MetaLeft);
|
||||
m.insert(0x5C, Key::MetaRight);
|
||||
m
|
||||
});
|
||||
|
||||
fn default_callback(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;
|
||||
|
||||
impl Robot {
|
||||
pub unsafe fn key_listen(callback: HookCallback) -> Result<(), windows::HookError> {
|
||||
if HOOK.is_null() {
|
||||
let r = windows::hook(WH_KEYBOARD_LL, Self::key_raw_callback);
|
||||
if KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||
let r = windows::hook(WH_KEYBOARD_LL, &*KEYBOARD_HHOOK, Self::key_raw_callback);
|
||||
|
||||
if r.is_err() {
|
||||
return Err(windows::HookError::Keyboard(r.err().unwrap()));
|
||||
}
|
||||
HOOK = r.ok().unwrap();
|
||||
}
|
||||
|
||||
HOOK_CALLBACK = callback;
|
||||
|
@ -283,12 +280,11 @@ impl Robot {
|
|||
}
|
||||
|
||||
pub unsafe fn key_unlisten() -> Result<(), windows::HookError> {
|
||||
if !HOOK.is_null() {
|
||||
let r = windows::unhook(HOOK);
|
||||
if !KEYBOARD_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||
let r = windows::unhook(&*KEYBOARD_HHOOK);
|
||||
if r.is_err() {
|
||||
return Err(windows::HookError::Keyboard(r.err().unwrap()));
|
||||
}
|
||||
HOOK = null_mut();
|
||||
}
|
||||
|
||||
HOOK_CALLBACK = default_callback;
|
||||
|
@ -299,37 +295,13 @@ impl Robot {
|
|||
pub fn key_press(key: Key) {
|
||||
let dw_flags = KEYEVENTF_SCANCODE;
|
||||
|
||||
let mut input = INPUT {
|
||||
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) };
|
||||
Self::keyboard_event(0, Self::key_to_scancode(key), dw_flags);
|
||||
}
|
||||
|
||||
pub fn key_release(key: Key) {
|
||||
let dw_flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
|
||||
|
||||
let mut input = INPUT {
|
||||
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) };
|
||||
Self::keyboard_event(0, Self::key_to_scancode(key), dw_flags);
|
||||
}
|
||||
|
||||
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 {
|
||||
match Self::key_2_virtual_key(key) {
|
||||
Some(vk) => unsafe { MapVirtualKeyW(vk as u32, 0) as u16 },
|
||||
|
@ -353,11 +348,28 @@ impl Robot {
|
|||
|
||||
unsafe extern "system" fn key_raw_callback(
|
||||
code: c_int,
|
||||
param: WPARAM,
|
||||
lpdata: LPARAM,
|
||||
w_param: WPARAM,
|
||||
l_param: LPARAM,
|
||||
) -> LRESULT {
|
||||
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 {
|
||||
let event = Event {
|
||||
event_type,
|
||||
|
@ -366,27 +378,7 @@ impl Robot {
|
|||
HOOK_CALLBACK(event);
|
||||
}
|
||||
}
|
||||
CallNextHookEx(HOOK, code, param, lpdata)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
CallNextHookEx(null_mut(), code, w_param, l_param)
|
||||
}
|
||||
|
||||
fn key_2_virtual_key(key: Key) -> Option<WORD> {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::ptr::null_mut;
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
use winapi::ctypes::c_int;
|
||||
use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM};
|
||||
use winapi::shared::windef::HHOOK;
|
||||
use winapi::shared::minwindef::{DWORD, HINSTANCE, LPARAM, LRESULT, WPARAM};
|
||||
use winapi::shared::windef::HHOOK__;
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
use winapi::um::winuser::{SetWindowsHookExA, UnhookWindowsHookEx};
|
||||
|
||||
use winapi::um::winuser::{SetWindowsHookExW, UnhookWindowsHookEx};
|
||||
pub mod keyboard;
|
||||
pub mod mouse;
|
||||
|
||||
|
@ -16,22 +16,28 @@ pub enum HookError {
|
|||
Keyboard(DWORD),
|
||||
}
|
||||
|
||||
pub unsafe fn hook(id_hook: c_int, callback: HookCallback) -> Result<HHOOK, DWORD> {
|
||||
let hook = SetWindowsHookExA(id_hook, Some(callback), null_mut(), 0);
|
||||
pub unsafe fn hook(
|
||||
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();
|
||||
return Err(error);
|
||||
}
|
||||
|
||||
Ok(hook)
|
||||
}
|
||||
|
||||
pub unsafe fn unhook(hook: HHOOK) -> Result<(), DWORD> {
|
||||
if hook.is_null() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
UnhookWindowsHookEx(hook);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unhook(hook_ptr: &AtomicPtr<HHOOK__>) -> Result<(), DWORD> {
|
||||
if !hook_ptr.load(Ordering::Relaxed).is_null() {
|
||||
UnhookWindowsHookEx(hook_ptr.load(Ordering::Relaxed));
|
||||
hook_ptr.store(null_mut(), Ordering::Relaxed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,37 +1,39 @@
|
|||
use crate::windows;
|
||||
use crate::{Button, Event, EventType, HookCallback, Robot};
|
||||
use std::convert::TryInto;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::mem::{size_of, transmute};
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||
use std::time::SystemTime;
|
||||
use winapi::ctypes::c_int;
|
||||
use winapi::shared::minwindef::{DWORD, LPARAM, LRESULT, WPARAM};
|
||||
use winapi::shared::windef::HHOOK;
|
||||
use winapi::shared::minwindef::{DWORD, HIWORD, LPARAM, LRESULT, WPARAM};
|
||||
use winapi::shared::windef::{HHOOK__, POINT};
|
||||
use winapi::um::winuser::{
|
||||
CallNextHookEx, GetAsyncKeyState, GetSystemMetrics, SendInput, HC_ACTION, INPUT, INPUT_MOUSE,
|
||||
LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN,
|
||||
MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP,
|
||||
MOUSEEVENTF_VIRTUALDESK, MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN,
|
||||
SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1,
|
||||
VK_XBUTTON2, WH_MOUSE_LL, WM_LBUTTONDOWN,
|
||||
CallNextHookEx, GetAsyncKeyState, GetCursorPos, GetSystemMetrics, SendInput, HC_ACTION, INPUT,
|
||||
INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_HWHEEL, MOUSEEVENTF_LEFTDOWN,
|
||||
MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_MOVE,
|
||||
MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK, MOUSEEVENTF_WHEEL,
|
||||
MOUSEINPUT, MSLLHOOKSTRUCT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN,
|
||||
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) {
|
||||
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;
|
||||
|
||||
impl Robot {
|
||||
pub unsafe fn mouse_listen(callback: HookCallback) -> Result<(), windows::HookError> {
|
||||
if HOOK.is_null() {
|
||||
let r = windows::hook(WH_MOUSE_LL, Self::mouse_raw_callback);
|
||||
if MOUSE_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||
let r = windows::hook(WH_MOUSE_LL, &*MOUSE_HHOOK, Self::mouse_raw_callback);
|
||||
|
||||
if r.is_err() {
|
||||
return Err(windows::HookError::Mouse(r.err().unwrap()));
|
||||
}
|
||||
HOOK = r.ok().unwrap();
|
||||
}
|
||||
|
||||
HOOK_CALLBACK = callback;
|
||||
|
@ -40,12 +42,11 @@ impl Robot {
|
|||
}
|
||||
|
||||
pub unsafe fn mouse_unlisten() -> Result<(), windows::HookError> {
|
||||
if !HOOK.is_null() {
|
||||
let r = windows::unhook(HOOK);
|
||||
if !MOUSE_HHOOK.load(Ordering::Relaxed).is_null() {
|
||||
let r = windows::unhook(&*MOUSE_HHOOK);
|
||||
if r.is_err() {
|
||||
return Err(windows::HookError::Mouse(r.err().unwrap()));
|
||||
}
|
||||
HOOK = null_mut();
|
||||
}
|
||||
|
||||
HOOK_CALLBACK = default_callback;
|
||||
|
@ -53,6 +54,17 @@ impl Robot {
|
|||
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) {
|
||||
let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) };
|
||||
let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) };
|
||||
|
@ -74,24 +86,14 @@ impl Robot {
|
|||
dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN;
|
||||
}
|
||||
|
||||
let mut input = INPUT {
|
||||
type_: INPUT_MOUSE,
|
||||
u: unsafe {
|
||||
transmute(MOUSEINPUT {
|
||||
dx: (dx - { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 / {
|
||||
GetSystemMetrics(SM_CXVIRTUALSCREEN)
|
||||
},
|
||||
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) };
|
||||
Self::mouse_event(
|
||||
(dx - unsafe { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535
|
||||
/ unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) },
|
||||
(dy - unsafe { GetSystemMetrics(SM_YVIRTUALSCREEN) }) * 65535
|
||||
/ unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) },
|
||||
0,
|
||||
dw_flags,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn mouse_press(button: Button) {
|
||||
|
@ -99,20 +101,7 @@ impl Robot {
|
|||
|
||||
let dw_flags = btn;
|
||||
|
||||
let mut input = INPUT {
|
||||
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) };
|
||||
Self::mouse_event(0, 0, 0, dw_flags);
|
||||
}
|
||||
|
||||
pub fn mouse_release(button: Button) {
|
||||
|
@ -120,13 +109,31 @@ impl Robot {
|
|||
|
||||
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 {
|
||||
type_: INPUT_MOUSE,
|
||||
u: unsafe {
|
||||
transmute(MOUSEINPUT {
|
||||
dx: 0,
|
||||
dy: 0,
|
||||
mouseData: 0,
|
||||
dx,
|
||||
dy,
|
||||
mouseData: mouse_data,
|
||||
dwFlags: dw_flags,
|
||||
time: 0,
|
||||
dwExtraInfo: 0,
|
||||
|
@ -136,10 +143,6 @@ impl Robot {
|
|||
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 {
|
||||
match ev {
|
||||
EventType::MousePress(button) => match button {
|
||||
|
@ -174,13 +177,47 @@ impl Robot {
|
|||
(mouse.pt.x, mouse.pt.y)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern "system" fn mouse_raw_callback(
|
||||
code: c_int,
|
||||
param: WPARAM,
|
||||
lpdata: LPARAM,
|
||||
w_param: WPARAM,
|
||||
l_param: LPARAM,
|
||||
) -> LRESULT {
|
||||
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 {
|
||||
let event = Event {
|
||||
event_type,
|
||||
|
@ -189,25 +226,6 @@ impl Robot {
|
|||
HOOK_CALLBACK(event);
|
||||
}
|
||||
}
|
||||
CallNextHookEx(HOOK, code, param, lpdata)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
CallNextHookEx(null_mut(), code, w_param, l_param)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user