Skip to content

Instantly share code, notes, and snippets.

@tholden
Forked from AWMooreCO/AdvancedWindowSnap.ahk
Last active November 15, 2019 15:11
Show Gist options
  • Save tholden/37a0d118b67b019a4dd3 to your computer and use it in GitHub Desktop.
Save tholden/37a0d118b67b019a4dd3 to your computer and use it in GitHub Desktop.

Advanced Window Snap

Advanced Window Snap is a script for AutoHotKey that expands upon Windows built-in window-snapping hotkeys (which are Win + LEFT to snap an active window to the left half of a monitor and Win + RIGHT to snap a window to the right half of a monitor) by adding many additional snap methods, using combinations of Win + Ctrl, Win + Alt, and Win + Ctrl + Alt, along with arrow keys, and the number pad (with NumLock On).

Installation Steps

  1. Install AutoHotKey
  2. Copy or Download the AdvancedWindowSnap.ahk file to your computer and double click it to run it.
  3. (Optional) To have the program run when you start up your computer, place the .ahk file into your computer's startup folder.
    • The Windows 7 Startup Folder can be accessed by mousing to Start > All Programs, then right-clicking on Startup and selecting "Open".
    • The Windows 8 Startup Folder can be accessed by tapping Win + R on your keyboard, then in the Open: field, type shell:startup then press Enter.

Advanced Window Snap Keybindings

Directional Arrow Hotkeys:

Please see the code.

Changelog

  • v2.00, 30 March 2015
    • Modified for widescreen monitors
  • v1.00, 08 January 2015
    • Initial Version

Recommendation For Editing AHK Files

If you plan on working with AutoHotKey files, consider using Sublime Text 3. Read my steps for setting up Sublime Text 3 to edit AutoHotKey files here: Working with AutoHotKey in Sublime Text.

/**
* Advanced Window Snap
* Snaps the Active Window to one of nine different window positions.
*
* @author Andrew Moore <andrew+github@awmoore.com>
* @version 1.0
*/
/**
* SnapActiveWindow resizes and moves (snaps) the active window to a given position.
* @param {string} winPlaceVertical The vertical placement of the active window.
* Expecting "top" or "bottom", otherwise assumes
* window should span the "full" height of the monitor.
* @param {string} winPlaceHorizontal The horizontal placement of the active window.
* Expecting "right" or "middle", otherwise assumes
* window should be placed at the "left".
* @param {string} winSizeWidth The width of the active window in relation to
* the active monitor's width. Expecting "full" or "half"
* size, otherwise will resize window to a "third".
*/
SnapActiveWindow(winPlaceVertical, winPlaceHorizontal, winSizeWidth) {
WinGet activeWin, ID, A
activeMon := GetMonitorIndexFromWindow(activeWin)
SysGet, MonitorWorkArea, MonitorWorkArea, %activeMon%
if (winSizeWidth == "full") {
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft)
} else if (winSizeWidth == "half") {
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft)/2
} else {
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft)/3
}
if (winPlaceVertical == "top") {
posY := MonitorWorkAreaTop
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop)/2
} else if (winPlaceVertical == "bottom") {
posY := MonitorWorkAreaTop + (MonitorWorkAreaBottom - MonitorWorkAreaTop)/2
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop)/2
} else {
posY := MonitorWorkAreaTop
height := MonitorWorkAreaBottom - MonitorWorkAreaTop
}
if (winPlaceHorizontal == "right") {
posX := MonitorWorkAreaRight - width
} else if (winPlaceHorizontal == "middle") {
posX := MonitorWorkAreaLeft + (MonitorWorkAreaRight - MonitorWorkAreaLeft - width)/2
} else {
posX := MonitorWorkAreaLeft
}
WinMove,A,,%posX%,%posY%,%width%,%height%
}
/**
* GetMonitorIndexFromWindow retrieves the HWND (unique ID) of a given window.
* @param {Uint} windowHandle
* @author shinywong
* @link http://www.autohotkey.com/board/topic/69464-how-to-determine-a-window-is-in-which-monitor/?p=440355
*/
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%
}
; Directional Arrow Hotkeys
#!^Left::SnapActiveWindow("full","left","half")
#!^Right::SnapActiveWindow("full","right","half")
#^!Up::SnapActiveWindow("top","full","full")
#^!Down::SnapActiveWindow("bottom","full","full")
#!Left::SnapActiveWindow("full","left","third")
#!Right::SnapActiveWindow("full","right","third")
#!Up::SnapActiveWindow("full","middle","third")
#!Down::SnapActiveWindow("full","middle","third")
#^Left::SnapActiveWindow("full","left","half")
#^Right::SnapActiveWindow("full","right","half")
#^Up::SnapActiveWindow("full","middle","half")
#^Down::SnapActiveWindow("full","middle","half")
; Numberpad Hotkeys
#!Numpad7::SnapActiveWindow("top","left","third")
#!Numpad8::SnapActiveWindow("top","middle","third")
#!Numpad9::SnapActiveWindow("top","right","third")
#!Numpad4::SnapActiveWindow("full","left","third")
#!Numpad5::SnapActiveWindow("full","middle","third")
#!Numpad6::SnapActiveWindow("full","right","third")
#!Numpad1::SnapActiveWindow("bottom","left","third")
#!Numpad2::SnapActiveWindow("bottom","middle","third")
#!Numpad3::SnapActiveWindow("bottom","right","third")
#^Numpad7::SnapActiveWindow("top","left","half")
#^Numpad8::SnapActiveWindow("top","middle","half")
#^Numpad9::SnapActiveWindow("top","right","half")
#^Numpad4::SnapActiveWindow("full","left","half")
#^Numpad5::SnapActiveWindow("full","middle","half")
#^Numpad6::SnapActiveWindow("full","right","half")
#^Numpad1::SnapActiveWindow("bottom","left","half")
#^Numpad2::SnapActiveWindow("bottom","middle","half")
#^Numpad3::SnapActiveWindow("bottom","right","half")
#!^Numpad7::SnapActiveWindow("top","left","full")
#!^Numpad8::SnapActiveWindow("top","middle","full")
#!^Numpad9::SnapActiveWindow("top","right","full")
#!^Numpad4::SnapActiveWindow("full","left","full")
#!^Numpad5::SnapActiveWindow("full","middle","full")
#!^Numpad6::SnapActiveWindow("full","right","full")
#!^Numpad1::SnapActiveWindow("bottom","left","full")
#!^Numpad2::SnapActiveWindow("bottom","middle","full")
#!^Numpad3::SnapActiveWindow("bottom","right","full")
@appel
Copy link

appel commented Dec 27, 2016

Awesome script, @tholden, thanks so much for posting it here. Total AHK beginner here: is there any way AHK can iterate through different parameters with the same shortcut? I would love to mimic this specific WinSplit Revolution feature that I have not been able to find anywhere else:

  • Press Win+5 (#Numpad5) once and it moves to the left half of the screen
  • Press Win+5 again and it resizes to one third of the screen
  • Press it again and it resized to two thirds
  • Press it again and it goes back to the first state: the left half of the screen
  • Same idea with the other numkey shortcuts

I tried copy pasting the same shortcut but AHK threw an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment