2020-11-25 13:37:18 +09:00
|
|
|
use std::mem::{size_of, transmute};
|
|
|
|
use winapi::ctypes::c_int;
|
|
|
|
use winapi::shared::minwindef::DWORD;
|
|
|
|
use winapi::um::winuser::{
|
2020-11-25 13:51:11 +09:00
|
|
|
GetAsyncKeyState, GetSystemMetrics, SendInput, INPUT, INPUT_MOUSE, LPINPUT, MOUSEEVENTF_ABSOLUTE,
|
2020-11-25 13:37:18 +09:00
|
|
|
MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP,
|
|
|
|
MOUSEEVENTF_MOVE, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_VIRTUALDESK,
|
2020-11-25 13:51:11 +09:00
|
|
|
MOUSEINPUT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN,
|
|
|
|
VK_LBUTTON, VK_MBUTTON, VK_RBUTTON, VK_XBUTTON1, VK_XBUTTON2,
|
2020-11-25 13:37:18 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
use crate::mouse::{Button, ButtonState, Mouse};
|
|
|
|
|
|
|
|
impl Mouse {
|
|
|
|
pub fn move_to(absolute: bool, dx: i32, dy: i32) {
|
2020-11-25 13:51:11 +09:00
|
|
|
let width = unsafe { GetSystemMetrics(SM_CXVIRTUALSCREEN) };
|
|
|
|
let height = unsafe { GetSystemMetrics(SM_CYVIRTUALSCREEN) };
|
|
|
|
if width == 0 || height == 0 {
|
|
|
|
return;
|
|
|
|
}
|
2020-11-25 13:37:18 +09:00
|
|
|
let pressed_left = Self::pressed(Button::Left);
|
|
|
|
let pressed_right = Self::pressed(Button::Right);
|
|
|
|
let pressed_middle = Self::pressed(Button::Middle);
|
|
|
|
let mut dw_flags = MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK;
|
|
|
|
|
|
|
|
if absolute {
|
|
|
|
dw_flags = dw_flags | MOUSEEVENTF_ABSOLUTE;
|
|
|
|
}
|
|
|
|
if pressed_left {
|
|
|
|
dw_flags = dw_flags | MOUSEEVENTF_LEFTDOWN;
|
|
|
|
}
|
|
|
|
if pressed_right {
|
|
|
|
dw_flags = dw_flags | MOUSEEVENTF_RIGHTDOWN;
|
|
|
|
}
|
|
|
|
if pressed_middle {
|
|
|
|
dw_flags = dw_flags | MOUSEEVENTF_MIDDLEDOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut input = INPUT {
|
|
|
|
type_: INPUT_MOUSE,
|
|
|
|
u: unsafe {
|
|
|
|
transmute(MOUSEINPUT {
|
2020-11-25 13:51:11 +09:00
|
|
|
dx: (dx - { GetSystemMetrics(SM_XVIRTUALSCREEN) }) * 65535 / {
|
|
|
|
GetSystemMetrics(SM_CXVIRTUALSCREEN)
|
|
|
|
},
|
|
|
|
dy: (dy - { GetSystemMetrics(SM_YVIRTUALSCREEN) }) * 65535 / {
|
|
|
|
GetSystemMetrics(SM_CYVIRTUALSCREEN)
|
|
|
|
},
|
2020-11-25 13:37:18 +09:00
|
|
|
mouseData: 0,
|
|
|
|
dwFlags: dw_flags,
|
|
|
|
time: 0,
|
|
|
|
dwExtraInfo: 0,
|
|
|
|
})
|
|
|
|
},
|
|
|
|
};
|
|
|
|
unsafe { SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int) };
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn press(button: Button) {
|
|
|
|
let btn = Self::button_event(button, ButtonState::Press);
|
|
|
|
|
|
|
|
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) };
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn release(button: Button) {
|
|
|
|
let btn = Self::button_event(button, ButtonState::Release);
|
|
|
|
|
|
|
|
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) };
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pressed(button: Button) -> bool {
|
|
|
|
(unsafe { GetAsyncKeyState(Self::button_virtual_key(button)) } >> 15) != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn button_event(button: Button, state: ButtonState) -> DWORD {
|
|
|
|
match state {
|
|
|
|
ButtonState::Press => match button {
|
|
|
|
Button::Left => MOUSEEVENTF_LEFTDOWN,
|
|
|
|
Button::Middle => MOUSEEVENTF_MIDDLEDOWN,
|
|
|
|
Button::Right => MOUSEEVENTF_RIGHTDOWN,
|
|
|
|
_ => unimplemented!(),
|
|
|
|
},
|
|
|
|
ButtonState::Release => match button {
|
|
|
|
Button::Left => MOUSEEVENTF_LEFTUP,
|
|
|
|
Button::Middle => MOUSEEVENTF_MIDDLEUP,
|
|
|
|
Button::Right => MOUSEEVENTF_RIGHTUP,
|
|
|
|
_ => unimplemented!(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn button_virtual_key(button: Button) -> c_int {
|
|
|
|
match button {
|
|
|
|
Button::Left => VK_LBUTTON,
|
|
|
|
Button::Middle => VK_MBUTTON,
|
|
|
|
Button::Right => VK_RBUTTON,
|
|
|
|
Button::X1 => VK_XBUTTON1,
|
|
|
|
Button::X2 => VK_XBUTTON2,
|
|
|
|
_ => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|