Lock mouse movement to only allow horizontal movement (vertical too if you want) Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
wooper

Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by wooper » 09 Feb 2020, 09:52

first post!

i'm wondering how to even do this ahk. i'd share what i'd have but I just thought of it...

i'd like some ideas please with this and the basis is in relation to drawing with a pencil or line tool in paint whilst holding shift. the mouse isn't necessarily locked on paint, but if you're moving in any direction with shift held, even if the mouse is also moving, the line is straight.

thanks

p.s. i'd use this for a game (coloring pixels on steam)

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 09 Feb 2020, 11:11

Try this:

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else
      MouseMove, A_EventInfo, NumGet(lParam+4, "UInt"), 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
I'm not sure if this will work in the game.

Raghava Doregowda
Posts: 130
Joined: 06 Nov 2022, 01:48

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by Raghava Doregowda » 06 Nov 2022, 01:56

teadrinker wrote:
09 Feb 2020, 11:11
Try this:

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else
      MouseMove, A_EventInfo, NumGet(lParam+4, "UInt"), 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
I'm not sure if this will work in the game.
Fantastic. This code you wrote is working perfectly. Thanks for taking the time to help all of us


gregparks
Posts: 2
Joined: 09 Jan 2023, 14:47

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by gregparks » 09 Jan 2023, 14:52

teadrinker wrote:
09 Feb 2020, 11:11
Try this:

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else
      MouseMove, A_EventInfo, NumGet(lParam+4, "UInt"), 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
I'm not sure if this will work in the game.
Hi teadrinker, where would you insert code in this script to have a tooltip display for the duration for which Ctrl or Shift is held? Just something simple like "mouse movement restricted."

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 09 Jan 2023, 18:44

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   ToolTip mouse movement restricted.
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   ToolTip
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else
      MouseMove, A_EventInfo, NumGet(lParam+4, "UInt"), 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
or

Code: Select all

~LShift::
~LCtrl::
   ToolTip mouse movement restricted.
   ClipCursor(A_ThisHotkey)
   KeyWait, % SubStr(A_ThisHotkey, 2)
   ClipCursor()
   ToolTip
   Return

ClipCursor(hk := "") {
   if !hk
      DllCall("ClipCursor", "Ptr", 0)
   else {
      CoordMode, Mouse
      MouseGetPos, X, Y
      VarSetCapacity(RECT, 16, 0)
      if InStr(hk, "Shift")
         NumPut(-0xFFFF, RECT, "Int"), NumPut(Y, RECT, 4), NumPut(0xFFFF, RECT, 8), NumPut(Y, RECT, 12, "Int")
      else
         NumPut(X, RECT), NumPut(X, RECT, 8), NumPut(A_ScreenHeight, RECT, 12, "Int")
      DllCall("ClipCursor", "Ptr", &RECT)
   }
}

gregparks
Posts: 2
Joined: 09 Jan 2023, 14:47

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by gregparks » 10 Jan 2023, 12:21

Thanks! I ended up putting the tooltip right under the SetMouseDelay so it stays on for as long as the script is running. I have my main script call up this script and exit when I'm done so I think it works better this way. Just out of curiosity, what's the difference between the 2 scripts you shared? Is one better than the other? Thanks!

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 10 Jan 2023, 13:25

gregparks wrote: Is one better than the other?
They just use two different approaches. I don't know which one is better, looks like both work equally well.

william_ahk
Posts: 481
Joined: 03 Dec 2018, 20:02

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)  Topic is solved

Post by william_ahk » 10 Jan 2023, 23:27

@teadrinker ClipCursor is better. It's smoother and consumes less resource than MouseHook as it's a native Windows function.

Btw, if anyone needs to confine mouse axis by moving direction, I've written a library for it a while ago: xy_mouse

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 10 Jan 2023, 23:57

william_ahk wrote: ClipCursor is better
I'm not sure. If you using ClipCursor start moving on one window and then click on another one, clipping fails.

william_ahk
Posts: 481
Joined: 03 Dec 2018, 20:02

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by william_ahk » 11 Jan 2023, 03:26

teadrinker wrote:
10 Jan 2023, 23:57
william_ahk wrote: ClipCursor is better
I'm not sure. If you using ClipCursor start moving on one window and then click on another one, clipping fails.
Ah ok, that I didn't notice :lol: I think it's worth patching it with more code though. It's a rare use case and the MouseHook method stutters a bit on my PC.

Raghava Doregowda
Posts: 130
Joined: 06 Nov 2022, 01:48

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by Raghava Doregowda » 26 Jan 2023, 15:08

teadrinker wrote:
09 Feb 2020, 11:11
Try this:

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else
      MouseMove, A_EventInfo, NumGet(lParam+4, "UInt"), 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
I'm not sure if this will work in the game.
Hey @teadrinker , Is it possible to implement this same code along with boosting the mouse speed? I want the mouse to go super fast (way more faster than what windows provides in the mouse options sliding tab) but it should move smoothly only vertically. So If I press Control and left click drag, the mouse movement should be fast and drag folders quickly in one vertical line

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 28 Jan 2023, 09:45

Raghava Doregowda wrote: I press Control and left click drag, the mouse movement should be fast and drag folders quickly in one vertical line
Try this:

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1
global y_prev := "", factor := 4

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   y_prev := ""
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else {
      (y_prev = "" && y_prev := NumGet(lParam+4, "UInt"))
      y := NumGet(lParam+4, "UInt")
      ((y_prev > A_ScreenHeight || y_prev < 0) && y_prev := y)
      MouseMove, A_EventInfo, y_prev := y + (y - y_prev)*factor, 0
   }
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
You can change the mouse speed by changing the factor variable.

Raghava Doregowda
Posts: 130
Joined: 06 Nov 2022, 01:48

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by Raghava Doregowda » 29 Jan 2023, 04:09

teadrinker wrote:
28 Jan 2023, 09:45
Raghava Doregowda wrote: I press Control and left click drag, the mouse movement should be fast and drag folders quickly in one vertical line
Try this:

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1
global y_prev := "", factor := 4

~LShift:: ; horizontal moving
~LCtrl::  ;   vertical moving
   y_prev := ""
   key := SubStr(A_ThisHotkey, 2)
   MouseGetPos, X_Mouse, Y_Mouse
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", key = "LCtrl" ? X_Mouse : 65536 | Y_Mouse)
   KeyWait, % key
   Hook := ""
   Return

LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   if (A_EventInfo >> 16)
      MouseMove, NumGet(lParam+0, "UInt"), A_EventInfo, 0
   else {
      (y_prev = "" && y_prev := NumGet(lParam+4, "UInt"))
      y := NumGet(lParam+4, "UInt")
      ((y_prev > A_ScreenHeight || y_prev < 0) && y_prev := y)
      MouseMove, A_EventInfo, y_prev := y + (y - y_prev)*factor, 0
   }
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
You can change the mouse speed by changing the factor variable.
Awesome! Is it possible to move it super fast if both X and Y axis are unlocked? Meaning If I press control and move the mouse it goes fast in all directions?

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 29 Jan 2023, 09:43

Raghava Doregowda wrote: If I press control and move the mouse it goes fast in all directions?

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1
global x_prev := "", y_prev := "", factor := 4

~LCtrl::
   x_prev := y_prev := ""
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc")
   KeyWait, LCtrl
   Hook := ""
Return
   
LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   x := NumGet(lParam+0, "UInt"), y := NumGet(lParam+4, "UInt")
   (x_prev = "" || x_prev < 0 || x_prev > A_ScreenWidth ) && (x_prev := x)
   (y_prev = "" || y_prev < 0 || y_prev > A_ScreenHeight) && (y_prev := y)
   MouseMove, x_prev := x + (x - x_prev)*factor, y_prev := y + (y - y_prev)*factor, 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}

Raghava Doregowda
Posts: 130
Joined: 06 Nov 2022, 01:48

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by Raghava Doregowda » 30 Jan 2023, 11:39

teadrinker wrote:
29 Jan 2023, 09:43
Raghava Doregowda wrote: If I press control and move the mouse it goes fast in all directions?

Code: Select all

CoordMode, Mouse
SetMouseDelay, -1
global x_prev := "", y_prev := "", factor := 4

~LCtrl::
   x_prev := y_prev := ""
   Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc")
   KeyWait, LCtrl
   Hook := ""
Return
   
LowLevelMouseProc(nCode, wParam, lParam) {
   if (wParam != 0x200)
      Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "Ptr", wParam, "Ptr", lParam)
   x := NumGet(lParam+0, "UInt"), y := NumGet(lParam+4, "UInt")
   (x_prev = "" || x_prev < 0 || x_prev > A_ScreenWidth ) && (x_prev := x)
   (y_prev = "" || y_prev < 0 || y_prev > A_ScreenHeight) && (y_prev := y)
   MouseMove, x_prev := x + (x - x_prev)*factor, y_prev := y + (y - y_prev)*factor, 0
   Return 1
}

class WindowsHook {
   __New(type, callback, eventInfo := "", isGlobal := true) {
      this.callbackPtr := RegisterCallback(callback, "Fast", 3, eventInfo)
      this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.callbackPtr
                                              , "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
                                              , "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
   }
   __Delete() {
      DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
      DllCall("GlobalFree", "Ptr", this.callBackPtr, "Ptr")
   }
}
It works as expected but just one problem. I have a dual monitor setup and the mouse is getting locked into only one monitor screen movement

teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Lock mouse movement to only allow horizontal movement (vertical too if you want)

Post by teadrinker » 30 Jan 2023, 12:08

Try to experiment with this block:

Code: Select all

   (x_prev = "" || x_prev < 0 || x_prev > A_ScreenWidth ) && (x_prev := x)
   (y_prev = "" || y_prev < 0 || y_prev > A_ScreenHeight) && (y_prev := y)

Post Reply

Return to “Ask for Help (v1)”