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

Get help with using AutoHotkey 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 183 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: 1318
Joined: 01 Oct 2013, 08:23
Location: Netherlands OS: Win7 x64 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.

Return to “Ask For Help”

Who is online

Users browsing this forum: Google [Bot], SAbboushi and 33 guests