Second Mouse Cursor

Post your working scripts, libraries and tools for AHK v1.1 and older
lord_ne
Posts: 7
Joined: 24 Dec 2016, 20:57

Second Mouse Cursor

01 Oct 2017, 22:05

This is a script I wrote that adds a second cursor to Windows. The cursor is controlled using a Joystick. Both right and left clicking are supported, but clicking and dragging is not. The clicks can be sent one of two ways, each of which have their own pros and cons. The first option is using ControlClick. This option has the advantage of usually being able to send a click without activating the target window, but the disadvantage of not always working properly, not to mention being an absolute nightmare to code. One the other hand, using MouseClick has the advantage of working far more reliably, but the disadvantage of requiring the target window to be activated, at least briefly.

Code: Select all

; Script by lord_ne

; Some code taken from the "Using a Joystick as a Mouse" sample script

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

ActiveMode = 1 ; 1 attempts to click without activating the target window (behavior may be inconsistent)
;                2 activates the target window but immediately deactivates it in favor of the previously active window
;                3 activates the target window and allows it to remain active (keyboard inputs will be sent to that window)

JoyMultiplier = 0.25 ; Multiplier for mouse speed

JoyThreshold = 3 ; Joystick threshold for mouse movement; prevents cursor drift

InvertYAxis := false ; "true" inverts the YAxis

JoystickNumber = 1 ; If you have multiple joysticks connected

Xres=1600
;   ↑↓ Screen resolution
Yres=900

CursorImage=C:\Users\Laptop\Documents\arrowicon.png ; Image to be used as second cursor

;End of config section. To change the Left and Right Click buttons, edit the hotkeys at the bottom of the script

#SingleInstance

JoystickPrefix = %JoystickNumber%Joy

JoyThresholdUpper := 50 + JoyThreshold
JoyThresholdLower := 50 - JoyThreshold
if InvertYAxis
    YAxisMultiplier = -1
else
    YAxisMultiplier = 1
	
Xpos=0

Ypos=0

Coordmode, Mouse, Screen

Gui, MouseGui: New, , Cursor
Gui, MouseGui:Margin , 0, 0
Gui, MouseGui:Add, Picture, +BackgroundTrans, %CursorImage%
Gui, MouseGui:Color, ECE9D8
Gui, MouseGui:+LastFound -Caption +AlwaysOnTop +ToolWindow -Border
Winset, TransColor, ECE9D8
Gui, MouseGui:Show, x%Xpos% y%Ypos% NoActivate, Cursor

SetTimer, WatchJoystick, 10  


return  ; End of auto-execute section.


WatchJoystick:
MouseNeedsToBeMoved := false  
SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY
if joyx > %JoyThresholdUpper%
{
    MouseNeedsToBeMoved := true
    DeltaX := joyx - JoyThresholdUpper
}
else if joyx < %JoyThresholdLower%
{
    MouseNeedsToBeMoved := true
    DeltaX := joyx - JoyThresholdLower
}
else
    DeltaX = 0
if joyy > %JoyThresholdUpper%
{
    MouseNeedsToBeMoved := true
    DeltaY := joyy - JoyThresholdUpper
}
else if joyy < %JoyThresholdLower%
{
    MouseNeedsToBeMoved := true
    DeltaY := joyy - JoyThresholdLower
}
else
    DeltaY = 0
if MouseNeedsToBeMoved
{
    Xpos:=Xpos+(DeltaX * JoyMultiplier)
	Ypos:=Ypos+(DeltaY * JoyMultiplier * YAxisMultiplier)
	if (Xpos<0)
	{
	  Xpos=0
	}
	if (Ypos<0)
	{
	  Ypos=0
	}
	if (Xpos>Xres)
	{
	  Xpos:=Xres
	}
	if (Ypos>Yres)
	{
	  Ypos:=Yres
	}
	
    Gui, MouseGui:Show, NoActivate x%Xpos% y%Ypos%, Cursor
}
return

!F1::
  ActiveMode=1
return

!F2::
  ActiveMode=2
return

!F3::
  ActiveMode=3
return

#If (ActiveMode = 1)

Joy5::
   PX:=Xpos - 1
   PY:=Ypos - 1
   VarSetCapacity(POINT, 8, 0)
   NumPut(PX, POINT, 0, "Int"), NumPut(PY, POINT, 4, "Int")
   HWND := DllCall("WindowFromPoint", "Int64", NumGet(POINT, 0, "Int64"))
   HWND := DllCall("GetAncestor", "UInt", HWND, "UInt", GA_ROOT := 2)
   WinExist("ahk_id" . HWND)
   WinGetTitle, Title
   WinGetClass, Class
   WinGetPos, X, Y, W, H
   XWin:= Xpos - X
   Ywin:= Ypos - Y
   WinGetTitle, TitleA, A
   SetControlDelay -1
   ControlClick, x%XWin% y%YWin%, %Title%, , LEFT, , NA
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
return

Joy6::
   PX:=Xpos - 1
   PY:=Ypos - 1
   VarSetCapacity(POINT, 8, 0)
   NumPut(PX, POINT, 0, "Int"), NumPut(PY, POINT, 4, "Int")
   HWND := DllCall("WindowFromPoint", "Int64", NumGet(POINT, 0, "Int64"))
   HWND := DllCall("GetAncestor", "UInt", HWND, "UInt", GA_ROOT := 2)
   WinExist("ahk_id" . HWND)
   WinGetTitle, Title
   WinGetClass, Class
   WinGetPos, X, Y, W, H
   XWin:= Xpos - X
   Ywin:= Ypos - Y
   WinGetTitle, TitleA, A
   SetControlDelay -1
   ControlClick, x%XWin% y%YWin%, %Title%, , RIGHT, , NA
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
return

#If (ActiveMode = 2)

Joy5::
   PX:=Xpos - 1
   PY:=Ypos - 1
   WinGetTitle, TitleA, A
   mousegetpos, start_x, start_y
   mouseclick, left, %PX%, %PY%, 1, 0
   mousemove, %start_x%, %start_y%, 0
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
return

Joy6::
   PX:=Xpos - 1
   PY:=Ypos - 1
   WinGetTitle, TitleA, A
   mousegetpos, start_x, start_y
   mouseclick, right, %PX%, %PY%, 1, 0
   mousemove, %start_x%, %start_y%, 0
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
   Sleep, 10
   WinActivate, %TitleA%
return

#If (ActiveMode = 3)

Joy5::
   PX:=Xpos - 1
   PY:=Ypos - 1
   mousegetpos, start_x, start_y
   mouseclick, left, %PX%, %PY%, 1, 0
   mousemove, %start_x%, %start_y%, 0
return

Joy6::
   PX:=Xpos - 1
   PY:=Ypos - 1
   mousegetpos, start_x, start_y
   mouseclick, right, %PX%, %PY%, 1, 0
   mousemove, %start_x%, %start_y%, 0

return
User avatar
Delta Pythagorean
Posts: 627
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: Second Mouse Cursor

04 Oct 2017, 18:35

Interesting way to move the second cursor. Maybe allow an arrow key movement? Maybe numpad? Still looks great! (Btw, add the icon for the cursor in the forum post ;D)

[AHK]......: v2.0.12 | 64-bit
[OS].......: Windows 11 | 23H2 (OS Build: 22621.3296)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat

User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: Second Mouse Cursor

09 Oct 2017, 05:49

BTW, if you used Interception, you could control the 2nd cursor with a 2nd mouse.
This is not normally possible, because RawInput can differentiate between devices, but cannot block (So the 2nd mouse would still move the main pointer), and Hooks cannot differentiate between devices (So you could not have the 2nd mouse only move the 2nd cursor), but can block.

Interception can differentiate between devices AND can block on a per-device basis.
Wafflesaraus
Posts: 11
Joined: 22 Oct 2017, 12:33

Re: Second Mouse Cursor

24 Oct 2017, 01:06

Would this method work so that only the second mouse sends clicks on a AHK Gui? I am attempting to make a touchscreen GUI that does not deactivate the main window.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 58 guests