Force the cursor to a curve: Line or circle

Post your working scripts, libraries and tools for AHK v1.1 and older
Rohwedder
Posts: 7656
Joined: 04 Jun 2014, 08:33
Location: Germany

Force the cursor to a curve: Line or circle

Post by Rohwedder » 05 Mar 2024, 08:26

The cursor will be bound to a curve, either a straight line or a circle.
Two points define a straight line, three points define a circle.
CursorOnCurve is controlled using the RControl and RButton keys:

When the cursor is at point 1, press the key combination RControl + RButton and release RControl. Now move the cursor to point 2 and release RButton.
The cursor is now bound to the straight line defined in this way, a state that can be switched off/on using RControl.

If the curve is to become a circle, the 3rd point required for this is defined between the above points, i.e. after point 1 and before point 2, move the cursor to point 3 and press and release RControl.

To delete the curve, enter RControl + RButton without moving the cursor.

Code: Select all

>^RButton:: ; CursorOnCurve
IF (OL.5 = "") {
OL:=[] ; OL is needed permanently, everything else only temporarily
Loop, 4 { ; bounding rectangle of all display monitors
    SysGet, q,% A_Index + 75
	OL[A_Index+5] := q
} OL.8 += OL.6, OL.9 += OL.7
} Else Gosub, OnCurveOff
CoordMode, Mouse, Screen
MouseGetPos, x1, y1
ToolTip,% OL.10:="OnLine: 1. Point recorded"
KeyWait, RButton
MouseGetPos, x2, y2
IF (OL.1:=x1) (OL.2:=y1) <> (OL.3:=x2) (OL.4:=y2) {
	OL.0:=OL.12:=True, OL.11 := DllCall("SetWindowsHookEx"
	,"Int", 14, "Ptr", RegisterCallback("CursorOnCurve")
	,"Ptr", DllCall("GetModuleHandle", "Ptr", 0, "Ptr"), "UInt", 0)
	(OL.5:=A_ThisHotkey="RCtrl")?OL.1:=Sqrt((x1-OL.2:=((x1*x1+y1*y1)
	*(y2-y3)+(x2*x2+y2*y2)*(y3-y1)+(x3*x3+y3*y3)*(y1-y2))/r0:=2*(x1
	*(y2-y3)+x2*(y3-y1)+x3*(y1-y2)))*(x1-OL.2)+(y1-OL.3:=((x1*x1+y1*y1)
	*(x3-x2)+(x2*x2+y2*y2)*(x1-x3)+(x3*x3+y3*y3)*(x2-x1))/r0)*(y1-OL.3))
	ToolTip,% RegExReplace(OL.10, "\d", 2)
	Sleep, 2000
	ToolTip,% OL.10:=""
	Return
} OnCurveOff:
	ToolTip,% OL.0:=OL.10:=OL.12:=""
	DllCall("UnhookWindowsHookEx", "Ptr", OL.11)
Return
#IF OL.0 ; if all necessary points are recorded
RCtrl Up::OL.11:=(OL.12:=!OL.12)?DllCall("SetWindowsHookEx"
, "Int", 14, "Ptr", RegisterCallback("CursorOnCurve")
, "Ptr", DllCall("GetModuleHandle", "Ptr", 0, "Ptr"), "UInt", 0)
:DllCall("UnhookWindowsHookEx", "Ptr", OL.11)
#IF OL.10 ; during point recording:
RCtrl:: ; toggles OnLine(2 Points) to OnCircle(3 Points)
#IF
CoordMode, Mouse, Screen
MouseGetPos, x3, y3
ToolTip,% OL.10:="OnCircle: 3. Point recorded"
Return
CursorOnCurve(nCode, wParam, lParam) {
    Global OL
    If (wParam = 0x0200) { ; WM_MOUSEMOVE 
        x := NumGet(lParam+0, "Short"), y := NumGet(lParam+4, "Short")
		IF OL.5 ; OnCircle OL.1=circle radius, OL.2/OL.3=x/y-center point
			x := OL.2+x*r0:=OL.1/Sqrt(x*(x-=OL.2)+y*(y-=OL.3)), y := OL.3+y*r0
		Else F := ((w:=OL.3-OL.1)*(x-OL.1)+(h:=OL.4-OL.2)*(y-OL.2))/(w*w+h*h)
			,x := Max(OL.6, Min(OL.1+F*w, OL.8)), y := Max(OL.7, Min(OL.2+F*h, OL.9))
        Return, !!DllCall("SetCursorPos", "int", x, "int", y) 
    }   Return, DllCall("CallNextHookEx", "UInt", 0, "Int"
        , nCode, "UInt", wParam, "UInt", lParam)
}
I use this script for the good old drawing program Picture Publisher 10.0 in order to use various tools along predefined curves.

Return to “Scripts and Functions (v1)”