"Normal" mouse wrapping for adjacent monitors set to a stacked arrangement in PC settings Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
AhkeyDokey
Posts: 2
Joined: 24 Nov 2017, 11:16

"Normal" mouse wrapping for adjacent monitors set to a stacked arrangement in PC settings

24 Nov 2017, 14:18

I'm looking for help with a mouse wrap script for two monitors that are set to display in a vertical stacked arrangement (PC settings) but located physically adjacent to one another. Want mouse to wrap from monitor [A] to without having to go through the bottom of monitor [A]. To clarify:
Untitled.png
Untitled.png (30.48 KiB) Viewed 1595 times
I've looked into several utilities (X-button Mouse Control, Dual Monitor Tools, etc) but none allow customization of the mouse wrapping from side of one screen to top of another. There's also DisplayFusion but the mouse feature$ co$t $.
User avatar
Nextron
Posts: 1391
Joined: 01 Oct 2013, 08:23
Location: Netherlands OS: Win10 AHK: Unicode x32

Re: "Normal" mouse wrapping for adjacent monitors set to a stacked arrangement in PC settings  Topic is solved

24 Nov 2017, 18:27

I once started with a script which moved the cursor based on its relative height/width when transitioning between monitors instead of absolute coordinates, in order to prevent the cursor from getting stuck behind corners of different sized screens. I made some changes to it so it should suit your need:

Code: Select all

Hook(a:=""){
	static init:=Hook(), hHookMouse:= DllCall("SetWindowsHookEx", "int", 14, "Uint", RegisterCallback("WH_MOUSE_LL", "Fast"), "Uint", 0, "Uint", 0), _:={base:{__Delete: "Hook"}}
	Global Config
	
	If !(init){
		Config:={}
		Config.Monitor:=[]
		Config.Warp:=[]
		Loop, % DllCall("GetSystemMetrics", "int", 80){ ;SM_CMONITORS
			SysGet, Mon, Monitor, %A_Index%
			Config.Monitor[A_Index]:={Left: MonLeft, Right: MonRight-1, Top: MonTop, Bottom: MonBottom-1, Width: MonRight-MonLeft, Height: MonBottom-MonTop}
		}
		
		;Set up all your warp edges here (works bidirectional)
		; e.g: Config.Warp.Push([1,"Right",3,"Left"])
		; 1: First monitor ID
		; 2: Active edge of first monitor: "Left", "Right", "Top" or "Bottom"
		; 3: Other monitor ID
		; 4: Active edge of other monitor, should be opposite side of #2
		
		Config.Warp.Push([1,"Left",2,"Right"])
		Return 1
	}
	
	If (!_){
		DllCall("UnhookWindowsHookEx", "Uint", hHookMouse)
		return
	}
}

WH_MOUSE_LL(nCode, wParam, lParam){
	Static MonitorTarget:=1, WasOnPad
	Global Config
	Critical

	if !nCode && (wParam = 0x200) { ;WM_MOUSEMOVE 

		mx := NumGet(lParam+0, 0, "Int")
		my := NumGet(lParam+0, 4, "Int")
		
		mxt:=Limit(Config.Monitor[MonitorTarget].Left,Config.Monitor[MonitorTarget].Right,mx)
		myt:=Limit(Config.Monitor[MonitorTarget].Top,Config.Monitor[MonitorTarget].Bottom,my)
		
		
		;~ For k,Mon in Config.Monitor
			;~ if (mx >= Mon.Left) && (mx <= Mon.Right) && (my >= Mon.Top) && (my <= Mon.Bottom){
				;~ Monitor:=k
				;~ Break
			;~ }
		
		For k,Warp in Config.Warp {
			Loop 2 { ;Bidirectional
				SourceMon:=Warp[2*A_Index-1]
				SourceEdge:=Warp[2*A_Index]
				TargetMon:=Warp[5-2*A_Index]
				TargetEdge:=Warp[6-2*A_Index] 
				If (SourceMon=MonitorTarget)
					If (SourceEdge="Left" || SourceEdge="Right") && mxt=Config.Monitor[SourceMon][SourceEdge]{
						OnPad:=1
						If !(WasOnPad){
							mxt:=Config.Monitor[TargetMon][TargetEdge]
							myt:=(myt-Config.Monitor[SourceMon].Top)*Config.Monitor[TargetMon].Height//Config.Monitor[SourceMon].Height+Config.Monitor[TargetMon].Top
							MonitorTarget:=TargetMon
							Break,2
						}
					}else If (SourceEdge="Top" || SourceEdge="Bottom") && myt=Config.Monitor[SourceMon][SourceEdge]{
						OnPad:=1
						If !(WasOnPad){
							mxt:=(mxt-Config.Monitor[SourceMon].Left)*Config.Monitor[TargetMon].Width//Config.Monitor[SourceMon].Width+Config.Monitor[TargetMon].Left
							myt:=Config.Monitor[TargetMon][TargetEdge]
							MonitorTarget:=TargetMon
							Break,2
						}
					}
			}
			
		}
		WasOnPad:=OnPad

		DllCall("SetCursorPos", "Int", mxt, "Int", myt)

		NumPut(mxt, lParam+0, 0, "Int")
		NumPut(myt, lParam+0, 4, "Int")
		DllCall("CallNextHookEx", "Uint", 0, "int", nCode, "Uint", wParam, "Uint", lParam)
		Return 1 
    
	}else Return DllCall("CallNextHookEx", "Uint", 0, "int", nCode, "Uint", wParam, "Uint", lParam) 
}  


Limit(Min,Max,Param){
	Return Param > Max ? Max : Param < Min ? Min : Param
}

Esc::ExitApp
The last line uses Escape to exit the script. Test the script, and if it works okay, you can remove that line.


Nice visual explanation btw. :thumbup:
AhkeyDokey
Posts: 2
Joined: 24 Nov 2017, 11:16

Re: "Normal" mouse wrapping for adjacent monitors set to a stacked arrangement in PC settings

25 Nov 2017, 22:21

GENIUS! Thank you so much. It works perfectly even in the context of an odd naming convention for primary (monitor #2) and secondary monitors (#1). There is no other utility available on the internet that does this. Excellent.
User avatar
JoeWinograd
Posts: 2198
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: "Normal" mouse wrapping for adjacent monitors set to a stacked arrangement in PC settings

04 Oct 2020, 13:37

Nextron wrote:script which moved the cursor based on its relative height/width when transitioning between monitors instead of absolute coordinates
Hi Nextron (or AhkeyDokey or anyone who wants to jump in),

I was searching the forum for help with this question that I posted yesterday:

Move mouse to center of monitor in multi-monitor configuration - CoordMode relative to specific monitor?

I found this thread that seems relevant, but I haven't been able to wrap my arms around your script. Could you please explain a little more about it and let me know if you think it can be used to solve my issue at the link above. Thanks much, Joe

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: RandomBoy and 283 guests