'script configuration:
'the monitor order and the monitor splits (horizontal and vertical) need to be specified.
'monitor order from left to right, top to bottom, is specified in MON_ORDER. the monitor splits
'are specified in MON_SPLIT_HORZ and MON_SPLIT_VERT.
'
'sample script configuration:
'your system has 3 monitors, monitor 3 on the left, monitor 1 at the center, and monitor 2 on the right.
'monitor 1 should be split in two vertically, and monitor 3 should be split in four (two horizontally
'and two vertically).
'the MON_ORDER, MON_SPLIT_HORZ and MON_SPLIT_VERT arrays would look like this:
'
'MON_ORDER = Array(3, 1, 2)
'MON_SPLIT_HORZ = Array(1, 1, 2)
'MON_SPLIT_VERT = Array(2, 1, 2)
'
'optional command-line arguments for the script:
'
'/n: move window to next monitor (default)
'/p: move window to previous monitor
'/r: only resize window if necessary (resize to fit). default is resize proportionally

Option Explicit
Dim MON_ORDER, MON_SPLIT_HORZ, MON_SPLIT_VERT
MON_ORDER = Array()
MON_SPLIT_HORZ = Array()
MON_SPLIT_VERT = Array()

If UBound(MON_ORDER) = -1 Then
	MsgBox "You'll need to configure the script before using it for the first time. To do this, right-click the script and select Edit from the menu, then read the instructions at the top of the script.",, "VMonMoveWnd"
	WScript.Quit
End If

Const SHOWSTATE_NORMAL = 2
Dim moveNext, resizeToFit, args
moveNext = True
resizeToFit = False
Set args = WScript.Arguments
For i = 0 To args.Count - 1
	Select Case args(i)
		Case "/n"
			moveNext = True
		Case "/p"
			moveNext = False
		Case "/r"
			resizeToFit = True
	End Select
Next

Dim wnd, curMon, i
Set wnd = CreateObject("UltraMon.Window")
If wnd.GetForegroundWindow() = True Then
	curMon = wnd.Monitor
	For i = 0 To UBound(MON_ORDER)
		If MON_ORDER(i) = curMon Then
			MoveWindow wnd, i, curMon - 1, moveNext, resizeToFit
			Exit For
		End If
	Next
End If

Sub MoveWindow(wnd, curMonIndex, curSplitIndex, moveNext, resizeToFit)
	Dim curLeft, curTop, curWidth, curHeight, sys, curMon, curMonLeft, curMonTop, curMonWidth, curMonHeight
	Dim newMonIndex, newSplitIndex, newMonLeft, newMonTop, newMonWidth, newMonHeight
	
	curLeft = wnd.Left
	curTop = wnd.Top
	curWidth = wnd.Width
	curHeight = wnd.Height
	
	Set sys = CreateObject("UltraMon.System")
	Set curMon = sys.Monitors(MON_ORDER(curMonIndex) - 1)
	curMonLeft = curMon.WorkLeft
	curMonTop = curMon.WorkTop
	curMonWidth = curMon.WorkWidth
	curMonHeight = curMon.WorkHeight
	
	newMonIndex = curMonIndex
	newSplitIndex = curSplitIndex
	newMonLeft = 0
	newMonTop = 0
	newMonWidth = 0
	newMonHeight = 0
	
	Dim splitX, splitY, len, offset, posX, posY
	splitX = MON_SPLIT_VERT(curSplitIndex)
	len = Int(curMonWidth / splitX)
	offset = curLeft - curMonLeft
	posX = 0
	If offset > 0 Then
		posX = Int(offset / len)
		If posX >= splitX Then posX = splitX - 1
	End If
	
	splitY = MON_SPLIT_HORZ(curSplitIndex)
	len = Int(curMonHeight / splitY)
	offset = curTop - curMonTop
	posY = 0
	If offset > 0 Then
		posY = Int(offset / len)
		If posY >= splitY Then posY = splitY - 1
	End If
	
	Dim split
	split = MON_SPLIT_VERT(curSplitIndex)
	If split > 1 Then
		curMonWidth = Int(curMonWidth / split)
		curMonLeft = curMonLeft + (posX * curMonWidth)
	End If
		
	split = MON_SPLIT_HORZ(curSplitIndex)
	If split > 1 Then
		curMonHeight = Int(curMonHeight / split)
		curMonTop = curMonTop + (posY * curMonHeight)
	End If
	
	'Dim msg
	'msg = "cur pos = " & MON_ORDER(curMonIndex) & " @ " & posX & "," & posY
	
	If moveNext Then
		posX = posX + 1
		If posX = splitX Then
			posX = 0
			posY = posY + 1
			If posY = splitY Then
				posY = 0
				newMonIndex = newMonIndex + 1
				If newMonIndex > UBound(MON_ORDER) Then newMonIndex = 0
				newSplitIndex = MON_ORDER(newMonIndex) - 1
			End If
		End If
	Else
		posX = posX - 1
		If posX < 0 Then
			posX = MON_SPLIT_VERT(curSplitIndex) - 1
			posY = posY - 1
			If posY < 0 Then
				newMonIndex = newMonIndex - 1
				If newMonIndex < 0 Then newMonIndex = UBound(MON_ORDER)
				newSplitIndex = MON_ORDER(newMonIndex) - 1
				posX = MON_SPLIT_VERT(newSplitIndex) - 1
				posY = MON_SPLIT_HORZ(newSplitIndex) - 1
			End If
		End If
	End If
	
	Dim newMon
	Set newMon = sys.Monitors(MON_ORDER(newMonIndex) - 1)
	newMonLeft = newMon.WorkLeft
	newMonTop = newMon.WorkTop
	newMonWidth = newMon.WorkWidth
	newMonHeight = newMon.WorkHeight
	
	split = MON_SPLIT_VERT(newSplitIndex)
	If split > 1 Then
		newMonWidth = Int(newMonWidth / split)
		newMonLeft = newMonLeft + (posX * newMonWidth)
	End If
		
	split = MON_SPLIT_HORZ(newSplitIndex)
	If split > 1 Then
		newMonHeight = Int(newMonHeight / split)
		newMonTop = newMonTop + (posY * newMonHeight)
	End If
	
	'MsgBox "split = " & split & " len = " & len & " offset = " & offset & " posX = " & posX & " posY = " & posY
	'MsgBox msg & " new pos = " & MON_ORDER(newMonIndex) & " @ " & posX & "," & posY
	'MsgBox "new mon: " & newMonWidth & " x " & newMonHeight & " @ " & newMonLeft & "," & newMonTop
	'Exit Sub
	
	If newMonWidth <> 0 Then
		Dim newLeft, newTop, newWidth, newHeight, offsetX, offsetY, offsetXRel, offsetYRel
		Dim newOffsetX, newOffsetY, relWidth, relHeight
		
		offsetX = curLeft - curMonLeft
		offsetY = curTop - curMonTop
				
		If newMonWidth = curMonWidth And newMonHeight = curMonHeight Then
			newLeft = newMonLeft + offsetX
			newTop = newMonTop + offsetY
			newWidth = curWidth
			newHeight = curHeight
		Else
			If resizeToFit = True Then
				offsetXRel = offsetX / curMonWidth
				offsetYRel = offsetY / curMonHeight
				newOffsetX = newMonWidth * offsetXRel
				newOffsetY = newMonHeight * offsetYRel
				
				newWidth = curWidth
				If newWidth > newMonWidth Then newWidth = newMonWidth
				newHeight = curHeight
				If newHeight > newMonHeight Then newHeight = newMonHeight
				
				If newOffsetX + newWidth > newMonWidth Then newOffsetX = newMonWidth - newWidth
				If newOffsetY + newHeight > newMonHeight Then newOffsetY = newMonHeight - newHeight
				
				newLeft = newMonLeft + newOffsetX
				newTop = newMonTop + newOffsetY
			Else
				offsetXRel = offsetX / curMonWidth
				offsetYRel = offsetY / curMonHeight
				relWidth = curWidth / curMonWidth
				relHeight = curHeight / curMonHeight
				newLeft = newMonLeft + newMonWidth * offsetXRel
				newTop = newMonTop + newMonHeight * offsetYRel
				newWidth = newMonWidth * relWidth
				newHeight = newMonHeight * relHeight
				
				'MsgBox "newWnd: " & newWidth & "x" & newHeight & " @ " & newLeft & "," & newTop
			End If
		End If
		
		wnd.ShowState = SHOWSTATE_NORMAL
		wnd.Left = newLeft
		wnd.Top = newTop
		wnd.Width = newWidth
		wnd.Height = newHeight
		wnd.ApplyChanges 0
	End If
End Sub