Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

Invert mouse axis


  • Please log in to reply
28 replies to this topic
Edwin
  • Guests
  • Last active:
  • Joined: --
This script was useful for me, because I needed a way to invert and swap the touchpad axes for my laptop.
It has an Intel Graphics chipset, which can rotate the screen by pressing control-alt-arrowkey. This, however, doesn't change the behavior of the touchpad cursor.

So I extended the script. The script has 3 global boolean variables which can be set to alter the cursor direction:
* swap_xy
* invert_x
* invert_y

The functions SetScreenEdges() and InitCursor() must be called prior of calling SetTimer InvertMouse, 1.
In my script I call this functions every time, because the dimensions of the screen change after a rotation.

Feel free to use the script and if you make improvements, please post them here.

SetScreenEdges() ; Initializes the screen dimensions
{
	global
	
	SysGet monitor_, Monitor
	monitor_left += 1, monitor_right -= 2, monitor_top += 1, monitor_bottom -= 2
}

InitCursor() ; Initializes the cursor position for the first time call
{
	global
	
	MouseGetPos x0, y0 ; get initial mouse pointer position
	x0 := (x0 < monitor_left) ? monitor_left : ( (x0 > monitor_right) ? monitor_right : x0)
	y0 := (y0 < monitor_top) ? monitor_top : ( (y0 > monitor_bottom) ? monitor_bottom : y0)
}

#SingleInstance force
#NoEnv
SetBatchLines -1
Process Priority, , R
BlockInput Mouse        ; user mouse input is ignored during MouseMove
CoordMode Mouse, Screen ; absolute coordinates
SetMouseDelay -1        ; fastest action
swap_xy := false
invert_x := false
invert_y := false
return

InvertMouse:
MouseGetPos x1, y1 ; get initial mouse pointer location

xdiff := (swap_xy) ? y1-y0 : x1-x0
ydiff := (swap_xy) ? x1-x0 : y1-y0

x0 += (invert_x) ? -xdiff : xdiff
y0 += (invert_y) ? -ydiff : ydiff

x0 := (xdiff) ? ( (x0 < monitor_left) ? monitor_left : ( (x0 > monitor_right) ? monitor_right : x0) ) : x0
y0 := (ydiff) ? ( (y0 < monitor_top) ? monitor_top : ( (y0 > monitor_bottom) ? monitor_bottom : y0) ) : y0

MouseMove x0, y0, 0 ; move the cursor and retain new position
return

~^!Up::
SetTimer InvertMouse, Off
return

~^!Right::
Sleep 200 ; wait until screen is rotated
SetScreenEdges()
InitCursor()
swap_xy := true
invert_x := false
invert_y := true
SetTimer InvertMouse, 1
return

~^!Down::
Sleep 200 ; wait until screen is rotated
SetScreenEdges()
InitCursor()
swap_xy := false
invert_x := true
invert_y := true
SetTimer InvertMouse, 1
return

~^!Left::
Sleep 200 ; wait until screen is rotated
SetScreenEdges()
InitCursor()
swap_xy := true
invert_x := true
invert_y := false
SetTimer InvertMouse, 1
return


redguy
  • Guests
  • Last active:
  • Joined: --
Thanks man. Very good job.

gonkarsha
  • Guests
  • Last active:
  • Joined: --
found a great freeware here flip x or y and roate
http://download.cnet... ... entBody;3d
it's called SakasaMouse 1.03

  • Guests
  • Last active:
  • Joined: --
I am looking for a script similar to one Laszlo made. I want it so when I press and hold my middle mouse button (mouse3), it inverts the y-axis, and when I release it, it goes back to normal. If this is not possible, is there a way to just assign it to a keyboard key combination?

None
  • Members
  • 3199 posts
  • Last active: Nov 05 2015 09:55 PM
  • Joined: 28 Nov 2009
;Laszlo's with minimal modification for Middle button Hotkey

#NoEnv 

SetBatchLines -1 

Process Priority,,R 



BlockInput Mouse        ; user mouse input is ignored during MouseMove 

CoordMode Mouse, Screen ; absolute coordinates 

SysGet m, Monitor       ; get the screen edges 

mTop += 1, mBottom -= 2 

SetMouseDelay -1        ; fastest action 



MButton::

MouseGetPos x0, y0      ; get initial mouse pointer location 

SetTimer WatchMouse, 1  ; run the subroutine fast (10..16ms) 

Return 

MButton Up::SetTimer WatchMouse, Off



WatchMouse: 

   MouseGetPos x, y     ; get current mouse position 

   y0 += 2*(y0-y), y0 := y0 < mTop  ? mTop  : (y0 > mBottom ? mBottom : y0) 

   MouseMove x, y0, 0  ; set new position as old, for the next timer 

Return 



!z::ExitApp             ; stop the madness; make the script persistent


  • Guests
  • Last active:
  • Joined: --
Perfect, thank you!!! :D

  • Guests
  • Last active:
  • Joined: --
Eeek, not so perfect. In the game I am trying to make this work for, if it gets close to the screen edges while inverted, it will scroll the opposite direction. How do I make it so it stays away (say 50 pixels) from the screen edges?

  • Guests
  • Last active:
  • Joined: --
Figured it out!

#NoEnv
SetBatchLines -1
Process Priority,,R

;BlockInput Mouse        ; user mouse input is ignored during MouseMove
;CoordMode Mouse, Screen ; absolute coordinates
;SysGet m, Monitor       ; get the screen edges
;mTop += 1, mBottom -= 2
;SetMouseDelay -1        ; fastest action

BlockInput Mouse        ; user mouse input is ignored during MouseMove
CoordMode Mouse, Screen ; absolute coordinates
SysGet m, Monitor       ; get the screen edges
mTop += 50, mBottom -= 50, mLeft += 50, mRight -= 50
SetMouseDelay -1        ; fastest action

MButton::
MouseGetPos x0, y0      ; get initial mouse pointer location
SetTimer WatchMouse, 1  ; run the subroutine fast (10..16ms)
Return
MButton Up::SetTimer WatchMouse, Off

WatchMouse:
   MouseGetPos x, y     ; get current mouse position
   y0 += y0-y, y0 := y0 < mTop  ? mTop  : (y0 > mBottom ? mBottom : y0)
   x0 += x-x0, x0 := x0 < mLeft ? mLeft : (x0 > mRight  ? mRight  : x0)
   MouseMove x0, y0, 0  ; set new position as old, for the next timer
Return

!z::ExitApp             ; stop the madness; make the script persistent


Raccoon
  • Members
  • 178 posts
  • Last active: Oct 06 2014 05:58 PM
  • Joined: 02 Jan 2008
The best method... mouse hook!

You can gut out all the commented code. It just shows the evolution of some parts of the code.

;By Raccoon Dec-2010
;Mouse Inverse using Mouse Hook

#SingleInstance, Force  ; Only one at a time.
#NoEnv         ; Just use it.
#Persistent    ; Needed if there are no hotkeys or timers.
OnExit, OnExit ; Needed to Unhook when Exiting.

hHookMouse := SetWindowsHookEx(14, RegisterCallback("WH_MOUSE_LL", "Fast"))

RETURN ; End Auto-execute.

OnExit:
  UnhookWindowsHookEx(hHookMouse) ; VERY IMPORTANT.
  ExitApp

WH_MOUSE_LL(nCode, wParam, lParam)
{
  Static lx:=999999, ly
  Critical
  
  if !nCode && (wParam = 0x200) { ; WM_MOUSEMOVE 

    mx := NumGet(lParam+0, 0, "Int") ; x-coord
    my := NumGet(lParam+0, 4, "Int") ; y-coord
    ;OutputDebug % "MouseMove : mx = " mx ", lx = " lx ", my = " my ", ly = " ly
    
    if (lx != 999999) { ; skip if last-xy coordinates haven't been initilized (first move).

      ; normal movement example.
      ;mx := lx + (mx - lx)
      ;my := ly + (my - ly)
      
      ; modify (invert) movement.
      mx := lx - (mx - lx)
      my := ly - (my - ly)
      
      ; modify (half-speed) movement.
      ;mx := lx + (mx - lx) / 2
      ;my := ly + (my - ly) / 2
      
      ; control desktop edges  /// this method is replaced by MouseGetPos or GetCursorPos below.
      ;if (mx < 0)
      ;  mx := 0
      ;else if (mx >= A_ScreenWidth)
      ;  mx := A_ScreenWidth -1
      ;if (my < 0)
      ;  my := 0
      ;else if (my >= A_ScreenHeight)
      ;  my := A_ScreenHeight -1
    }
    
    ; This is where the magic happens, in combination with Return 1.
    DllCall("SetCursorPos", "Int", mx, "Int", my)

    ;CoordMode, Mouse, Screen ; only needed if using MouseGetPos,
    ;MouseGetPos, lx, ly      ; lets use GetCursorPos instead.
    VarSetCapacity(lpPoint,8)
    DllCall("GetCursorPos", "Uint", &lpPoint) ; SetCursorPos controls desktop edges; less math for us.
    lx := NumGet(lpPoint, 0, "Int")
    ly := NumGet(lpPoint, 4, "Int")
    
    ; Send the modified mouse coords to other hooking processes along the chain.
    NumPut(mx, lParam+0, 0, "Int")
    NumPut(my, lParam+0, 4, "Int")
    ret:=DllCall("CallNextHookEx", "Uint", 0, "int", nCode, "Uint", wParam, "Uint", lParam)
    ;Return ret
    
    Return 1 ; Halt default mouse processing. (same method used by 'BlockInput, MouseMove')
  }
  else {
    Return DllCall("CallNextHookEx", "Uint", 0, "int", nCode, "Uint", wParam, "Uint", lParam) 
  }
} ; End WH_MOUSE_LL

SetWindowsHookEx(idHook, pfn)
{
  Return DllCall("SetWindowsHookEx", "int", idHook, "Uint", pfn, "Uint", DllCall("GetModuleHandle", "Uint", 0), "Uint", 0)
}

UnhookWindowsHookEx(hHook)
{
  Return DllCall("UnhookWindowsHookEx", "Uint", hHook)
}

; Since the below function is called so frequently, it's faster to use the DllCall() instead of this func.
CallNextHookEx(nCode, wParam, lParam, hHook = 0)
{
  Return DllCall("CallNextHookEx", "Uint", hHook, "int", nCode, "Uint", wParam, "Uint", lParam)
}

Posted Image

Need help right away? Get live support on IRC.
Already have an IRC client installed? /join #ahk

phunqe
  • Members
  • 2 posts
  • Last active: Feb 06 2011 11:37 AM
  • Joined: 04 Feb 2011

The best method... mouse hook!


Thank you very much for this code, it works.

I am trying to get it to work with the #IfWinActive statement and I realize it will not work with this kind of hook setup (correct me if I'm wrong).
So I was thinking, maybe it would be possible to add an active window check in the code as well, which will load and unload the hook?

I'll fiddle with it myself, but I am new at AHK so my mileage may vary. If you have any tips I would be grateful :)

Cheers.

EDIT: Never mind, it was rather simple really, just used a IfWinActive block around the invert code and a restore axis code in else :)

phunqe
  • Members
  • 2 posts
  • Last active: Feb 06 2011 11:37 AM
  • Joined: 04 Feb 2011
I am trying to use the hook version in a game but it doesn't work. I assume it's because of DirectInput. There are various tricks to normal scripts to use, but I have no idea how to do this with the hook version, if it's even possible?

Any tips?

Thanks.

EDIT: I just realized... It's an FPS game with free look, so I am not sure how mouse coordinates really works in that case, since they are not absolute. The hook script works when I toggle off free look in game to move the cursor around, but when going into free look it doesn't work. I am guessing something like "dragging" the mouse must be used, since it's not about placing the mouse somewhere, it's about the travel distance so to speak.
If that is making any sense whatsoever, I am not sure myself :p

Vibhor
  • Guests
  • Last active:
  • Joined: --
But,while working with C++, the cursor keeps moving towards right.

  • Guests
  • Last active:
  • Joined: --

I am looking for a script similar to one Laszlo made. I want it so when I press and hold my middle mouse button (mouse3), it inverts the y-axis, and when I release it, it goes back to normal. If this is not possible, is there a way to just assign it to a keyboard key combination?


;Laszlo's with minimal modification for Middle button Hotkey
#NoEnv 
SetBatchLines -1 
Process Priority,,R 

BlockInput Mouse        ; user mouse input is ignored during MouseMove 
CoordMode Mouse, Screen ; absolute coordinates 
SysGet m, Monitor       ; get the screen edges 
mTop += 1, mBottom -= 2 
SetMouseDelay -1        ; fastest action 

MButton::
MouseGetPos x0, y0      ; get initial mouse pointer location 
SetTimer WatchMouse, 1  ; run the subroutine fast (10..16ms) 
Return 
MButton Up::SetTimer WatchMouse, Off

WatchMouse: 
   MouseGetPos x, y     ; get current mouse position 
   y0 += 2*(y0-y), y0 := y0 < mTop  ? mTop  : (y0 > mBottom ? mBottom : y0) 
   MouseMove x, y0, 0  ; set new position as old, for the next timer 
Return 

!z::ExitApp             ; stop the madness; make the script persistent


I'm trying to reverse the x and y axis while holding down middle mouse for the dota 2 beta since this option isn't available yet for some reason. In game the middle button is supposed to grab the camera but for some reason the middle click is only being applied to the script.
I need a version of this script that also switches around the x axis and also activates left click and the m key while holding down middle mouse. Help would be greatly appreciated.

Lord Asriel
  • Members
  • 7 posts
  • Last active: Sep 05 2016 10:12 AM
  • Joined: 15 Mar 2014

Lazlo, I want to make a script based on yours. Maybe the following bit of information would be useful (obviously whoever else understands may answer):

 

x0 += 2*(x0-x), x0 := x0 < mLeft ? mLeft : (x0 > mRight ? mRight : x0)

 

Why is there a 2 here? Shouldn't it be 1 if the revere speed is to be the same?