【问题标题】:How can I capture and send raw mouse input in Autohotkey?如何在 Autohotkey 中捕获和发送原始鼠标输入?
【发布时间】:2017-10-28 21:23:15
【问题描述】:

我知道如何捕捉相对于屏幕的一般鼠标移动,但是在独立于鼠标在屏幕上的位置使用鼠标移动的游戏中呢?

例如,在游戏中,您的光标是隐藏的,但您可以无限期地向左移动鼠标并转圈,远远超出鼠标在屏幕上移动的空间。游戏可能会将您的隐形鼠标锁定在中心,或者让它移动直到它碰到窗口的边缘,但此时任何记录鼠标相对于屏幕移动的尝试都是无用的。

那么我怎样才能捕获/发送原始鼠标输入。例如,如果我想通过鼠标输入告诉玩家向左转 1000 度,并记录玩家向左转 1000 度的鼠标输入,我该怎么做呢?

我的最终目标是记录玩家的各种控制,包括鼠标输入,以创建记录和回放用户输入的系统之一。我搜索了整个 ahk 文档和谷歌,并没有发现任何关于捕获和发送原始鼠标输入的信息。

【问题讨论】:

    标签: autohotkey


    【解决方案1】:

    这已由 AHK 论坛上一位名叫 evilC 的出色用户为您处理。

    它被称为 mouse delta 并跟踪原始鼠标输入的变化。

    我已经发布了他的鼠标增量脚本的几个不同变体之一。确保您按照上面的链接查看他所做的所有不同的事情。

    再说一遍,这不是我的工作。

    ; 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)
        ;~ }
    
    }
    

    【讨论】:

    • 你是怎么用这个的?
    猜你喜欢
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多