如何在Autohotkey中捕获和发送原始鼠标输入?
我知道如何捕捉相对于屏幕的鼠标移动,但是在游戏中,鼠标移动是独立于鼠标在屏幕上的位置使用的,那又如何呢 例如,在游戏中,你的光标是隐藏的,但你可以无限地向左移动鼠标,然后转一圈,远远超过你的鼠标在屏幕上移动的空间。游戏可能会将你的隐形鼠标锁定在中间,或者让它移动直到它碰到窗口边缘,但在这一点上,任何记录鼠标相对于屏幕移动的尝试都是无用的 因此,如何捕获/发送原始鼠标输入。例如,如果我想通过鼠标输入告诉玩家向左转1000度,并记录玩家向左转1000度时的鼠标输入,我如何同时执行这两项操作如何在Autohotkey中捕获和发送原始鼠标输入?,autohotkey,Autohotkey,我知道如何捕捉相对于屏幕的鼠标移动,但是在游戏中,鼠标移动是独立于鼠标在屏幕上的位置使用的,那又如何呢 例如,在游戏中,你的光标是隐藏的,但你可以无限地向左移动鼠标,然后转一圈,远远超过你的鼠标在屏幕上移动的空间。游戏可能会将你的隐形鼠标锁定在中间,或者让它移动直到它碰到窗口边缘,但在这一点上,任何记录鼠标相对于屏幕移动的尝试都是无用的 因此,如何捕获/发送原始鼠标输入。例如,如果我想通过鼠标输入告诉玩家向左转1000度,并记录玩家向左转1000度时的鼠标输入,我如何同时执行这两项操作 我的目标
我的目标是最终记录玩家的各种控制,包括鼠标输入,以创建一个记录和回放用户输入的系统。我搜索了所有的ahk文档和谷歌,没有发现任何关于捕获和发送原始鼠标输入的信息 这已经由AHK论坛上一位名为evic的优秀用户为您解决了 它被调用并跟踪原始鼠标输入中的更改 我已经发布了他的鼠标增量脚本的几个不同变体之一。确保您按照上面的链接查看他所做的所有不同的操作 再说一遍,这不是我的工作
; Instantiate this class and pass it a func name or a Function Object
; The specified function will be called with the delta move for the X and Y axes
; Normally, there is no windows message "mouse stopped", so one is simulated.
; After 10ms of no mouse movement, the callback is called with 0 for X and Y
Class MouseDelta {
State := 0
__New(callback){
;~ this.TimeoutFn := this.TimeoutFunc.Bind(this)
this.MouseMovedFn := this.MouseMoved.Bind(this)
this.Callback := callback
}
Start(){
static DevSize := 8 + A_PtrSize, RIDEV_INPUTSINK := 0x00000100
; Register mouse for WM_INPUT messages.
VarSetCapacity(RAWINPUTDEVICE, DevSize)
NumPut(1, RAWINPUTDEVICE, 0, "UShort")
NumPut(2, RAWINPUTDEVICE, 2, "UShort")
NumPut(RIDEV_INPUTSINK, RAWINPUTDEVICE, 4, "Uint")
; WM_INPUT needs a hwnd to route to, so get the hwnd of the AHK Gui.
; It doesn't matter if the GUI is showing, it still exists
Gui +hwndhwnd
NumPut(hwnd, RAWINPUTDEVICE, 8, "Uint")
this.RAWINPUTDEVICE := RAWINPUTDEVICE
DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
OnMessage(0x00FF, this.MouseMovedFn)
this.State := 1
return this ; allow chaining
}
Stop(){
static RIDEV_REMOVE := 0x00000001
static DevSize := 8 + A_PtrSize
OnMessage(0x00FF, this.MouseMovedFn, 0)
RAWINPUTDEVICE := this.RAWINPUTDEVICE
NumPut(RIDEV_REMOVE, RAWINPUTDEVICE, 4, "Uint")
DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
this.State := 0
return this ; allow chaining
}
SetState(state){
if (state && !this.State)
this.Start()
else if (!state && this.State)
this.Stop()
return this ; allow chaining
}
Delete(){
this.Stop()
;~ this.TimeoutFn := ""
this.MouseMovedFn := ""
}
; Called when the mouse moved.
; Messages tend to contain small (+/- 1) movements, and happen frequently (~20ms)
MouseMoved(wParam, lParam){
Critical
; RawInput statics
static DeviceSize := 2 * A_PtrSize, iSize := 0, sz := 0, pcbSize:=8+2*A_PtrSize, offsets := {x: (20+A_PtrSize*2), y: (24+A_PtrSize*2)}, uRawInput
static axes := {x: 1, y: 2}
; Get hDevice from RAWINPUTHEADER to identify which mouse this data came from
VarSetCapacity(header, pcbSize, 0)
If (!DllCall("GetRawInputData", "UPtr", lParam, "uint", 0x10000005, "UPtr", &header, "Uint*", pcbSize, "Uint", pcbSize) or ErrorLevel)
Return 0
ThisMouse := NumGet(header, 8, "UPtr")
; Find size of rawinput data - only needs to be run the first time.
if (!iSize){
r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + (A_PtrSize * 2))
VarSetCapacity(uRawInput, iSize)
}
sz := iSize ; param gets overwritten with # of bytes output, so preserve iSize
; Get RawInput data
r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", sz, "UInt", 8 + (A_PtrSize * 2))
x := 0, y := 0 ; Ensure we always report a number for an axis. Needed?
x := NumGet(&uRawInput, offsets.x, "Int")
y := NumGet(&uRawInput, offsets.y, "Int")
this.Callback.(ThisMouse, x, y)
;~ ; There is no message for "Stopped", so simulate one
;~ fn := this.TimeoutFn
;~ SetTimer, % fn, -50
}
;~ TimeoutFunc(){
;~ this.Callback.("", 0, 0)
;~ }
}
这个怎么用?