I get by with an auto-hot-key script that adds a little to the standard Windows Alt-Arrow arrangement.
Windows 7 and up have Alt-Left and Alt-Right that move the window to the left and right edges. My AHK script (below) makes Alt-Up and Alt-Down move to the top and bottom edges, while Alt-PgUp and Alt-PgDown maximize and minimize, respectively.
; from https://autohotkey.com/board/topic/69464-how-to-determine-a-window-is-in-which-monitor/
; Tells you which monitor a window is on (given a windowhandle)
GetMonitorIndexFromWindow(windowHandle)
{
; Starts with 1.
monitorIndex := 1
VarSetCapacity(monitorInfo, 40)
NumPut(40, monitorInfo)
if (monitorHandle := DllCall("MonitorFromWindow", "uint", windowHandle, "uint", 0x2))
&& DllCall("GetMonitorInfo", "uint", monitorHandle, "uint", &monitorInfo)
{
monitorLeft := NumGet(monitorInfo, 4, "Int")
monitorTop := NumGet(monitorInfo, 8, "Int")
monitorRight := NumGet(monitorInfo, 12, "Int")
monitorBottom := NumGet(monitorInfo, 16, "Int")
workLeft := NumGet(monitorInfo, 20, "Int")
workTop := NumGet(monitorInfo, 24, "Int")
workRight := NumGet(monitorInfo, 28, "Int")
workBottom := NumGet(monitorInfo, 32, "Int")
isPrimary := NumGet(monitorInfo, 36, "Int") & 1
SysGet, monitorCount, MonitorCount
Loop, %monitorCount%
{
SysGet, tempMon, Monitor, %A_Index%
; Compare location to determine the monitor index.
if ((monitorLeft = tempMonLeft) and (monitorTop = tempMonTop)
and (monitorRight = tempMonRight) and (monitorBottom = tempMonBottom))
{
monitorIndex := A_Index
break
}
}
}
return monitorIndex
}
; Windows monitors are numbered from 1 up.
; Find the windowhandle for the 'active' window
; (might be none!)
GetMonitorIndexForActiveWindow()
{
winHand := WinExist("A")
if !winHand
return 0
return GetMonitorIndexFromWindow(winHand)
}
; Maximize current window
#PgUp::
WinMaximize, A
return
; Minimize current window
#PgDn::
WinMinimize, A
return
; Make active window take up top half of active monitor
#Up::
;Get the index of the monitor the active window is on (1, 2, etc. 0 if no active wind)
monIdx := GetMonitorIndexForActiveWindow()
if (monIdx)
{
; Get bounding box of that monitor
SysGet, MonBnd, Monitor, %monIdx%
; monitor height
monHi := (MonBndBottom-MonBndTop)
; monitor width
monWid := (MonBndRight - MonBndLeft)
; half height
newHi := monHi/2
WinMove, A, , %MonBndLeft%, %MonBndTop%, %monWid%, %newHi%
}
return
#Down::
;Get the index of the monitor the active window is on (1, 2, etc. 0 if no active wind)
monIdx := GetMonitorIndexForActiveWindow()
if (monIdx)
{
; Get bounding box of that monitor
SysGet, MonBnd, Monitor, %monIdx%
monHi := (MonBndBottom-MonBndTop)
; monitor width
monWid := (MonBndRight - MonBndLeft)
newTop := MonBndTop + (monHi/2)
newHi := monHi/2
WinMove, A, , %MonBndLeft%, %newTop%, %monWid%, %newHi%
}
return
Also, in a comment on another answer, Dimblefeck references Another AHK script which uses the num pad for window tiling control. I love that idea, but I can't personally bear to give up the number pad.