'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, with the left half 75% wide, and the right half 25% wide.
'monitor 3 should be split in four (two horizontally and two vertically), with each quadrant having the same size.
'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("", "", "0.5,0.5")
'MON_SPLIT_VERT = Array("0.75,0.25", "", "0.5,0.5")
'
'optional command-line arguments for the script:
'
'/m: maximize window after moving it
'/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.",, "VMonMoveWnd2"
	WScript.Quit
End If

Const SHOWSTATE_NORMAL = 2
Dim moveNext, resizeToFit, args, maximize
moveNext = True
resizeToFit = False
maximize = False
Set args = WScript.Arguments
For i = 0 To args.Count - 1
	Select Case args(i)
		Case "/m"
			maximize = True
		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 xPos, yPos, posX, posY
	GetSplitPos sys, curMonIndex, curSplitIndex, xPos, yPos
	
	posX = 0
	For i = 0 To UBound(xPos) - 1
		If curLeft >= xPos(i) And curLeft < xPos(i + 1) Then
			posX = i
			Exit For
		End If
	Next
	
	posY = 0
	For i = 0 To UBound(yPos) - 1
		If curTop >= yPos(i) And curTop < yPos(i + 1) Then
			posY = i
			Exit For
		End If
	Next
	
	curMonLeft = xPos(posX)
	curMonWidth = xPos(posX + 1) - curMonLeft
	curMonTop = yPos(posY)
	curMonHeight = yPos(posY + 1) - curMonTop
	
	'msgbox "curMon: " & curMonLeft & "," & curMonTop & " " & curMonWidth & "," & curMonHeight
	
	If moveNext Then
		posX = posX + 1
		If posX = UBound(xPos) Then
			posX = 0
			posY = posY + 1
			If posY = UBound(yPos) 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
			posY = posY - 1
			If posY < 0 Then
				newMonIndex = newMonIndex - 1
				If newMonIndex < 0 Then newMonIndex = UBound(MON_ORDER)
				newSplitIndex = MON_ORDER(newMonIndex) - 1
			End If
		End If
	End If
	
	GetSplitPos sys, newMonIndex, newSplitIndex, xPos, yPos
	
	If posX = -1 Then posX = UBound(xPos) - 1
	If posY = -1 Then posY = UBound(yPos) - 1
	
	newMonLeft = xPos(posX)
	newMonWidth = xPos(posX + 1) - newMonLeft
	newMonTop = yPos(posY)
	newMonHeight = yPos(posY + 1) - newMonTop
	
	'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
		
		If maximize = True Then
			newLeft = newMonLeft
			newTop = newMonTop
			newWidth = newMonWidth
			newHeight = newMonHeight
		Else
			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
		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

Sub GetSplitPos(sys, monIndex, splitIndex, xPos, yPos)
	Dim mon, monLeft, monTop, monWidth, monHeight
	Set mon = sys.Monitors(MON_ORDER(monIndex) - 1)
	monLeft = mon.WorkLeft
	monTop = mon.WorkTop
	monWidth = mon.WorkWidth
	monHeight = mon.WorkHeight
	
	Dim xSplits, splitX, ySplits, splitY, i
	splitX = MON_SPLIT_VERT(splitIndex)
	If splitX = "" Then splitX = "1.0"
	xSplits = Split(splitX, ",")
	ReDim xPos(UBound(xSplits) + 1)
	xPos(0) = monLeft
	For i = 1 To UBound(xSplits)
		xPos(i) = Int(xPos(i - 1) + (CDbl(xSplits(i - 1)) * monWidth))
		'msgbox "xPos(" & i & ") = " & xPos(i)
	Next
	xPos(UBound(xPos)) = monLeft + monWidth
	
	splitY = MON_SPLIT_HORZ(splitIndex)
	If splitY = "" Then splitY = "1.0"
	ySplits = Split(splitY, ",")
	ReDim yPos(UBound(ySplits) + 1)
	yPos(0) = monTop
	For i = 1 To UBound(ySplits)
		yPos(i) = Int(yPos(i - 1) + (CDbl(ySplits(i - 1)) * monHeight))
		'msgbox "yPos(" & i & ") = " & yPos(i)
	Next
	yPos(UBound(yPos)) = monTop + monHeight
End Sub