Instantly share code, notes, and snippets.

Embed
What would you like to do?
Advanced Window Snap is a script for AutoHotKey that expands upon Windows built-in window-snapping hotkeys.

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 9 additional snap methods.

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:

Hotkey Behavior
Win + Alt + UP Window will snap to the top half of the screen.
Win + Alt + DOWN Window will snap to the bottom half of the screen.
Ctrl + Win + Alt + UP Window will snap to the top third of the screen.
Ctrl + Win + Alt + DOWN Window will snap to the bottom third of the screen.

Numberpad Hotkeys (Landscape):

These will work only if you have NumLock turned ON. These are ideal for Landscape Monitors.

Hotkey Behavior
Win + Alt + Numpad 7 Window will snap to the top-left quarter of the screen.
Win + Alt + Numpad 8 Window will snap to the top half of the screen.
Win + Alt + Numpad 9 Window will snap to the top-right quarter of the screen.
Win + Alt + Numpad 1 Window will snap to the bottom-left quarter of the screen.
Win + Alt + Numpad 2 Window will snap to the bottom half of the screen.
Win + Alt + Numpad 3 Window will snap to the bottom-right quarter of the screen.

Numberpad Hotkeys (Portrait):

These will work only if you have NumLock turned ON. These are ideal for Portrait Monitors.

Hotkey Behavior
Ctrl + Win + Alt + Numpad 8 Window will snap to the top third of the screen.
Ctrl + Win + Alt + Numpad 5 Window will snap to the middle third of the screen.
Ctrl + Win + Alt + Numpad 2 Window will snap to the bottom third of the screen

Changelog

  • v1.00, 08 Jan 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 "bottom" or "middle", otherwise assumes
* "top" placement.
* @param {string} winPlaceHorizontal The horizontal placement of the active window.
* Expecting "left" or "right", otherwise assumes
* window should span the "full" width of the monitor.
* @param {string} winSizeHeight The height of the active window in relation to
* the active monitor's height. Expecting "half" size,
* otherwise will resize window to a "third".
*/
SnapActiveWindow(winPlaceVertical, winPlaceHorizontal, winSizeHeight) {
WinGet activeWin, ID, A
activeMon := GetMonitorIndexFromWindow(activeWin)
SysGet, MonitorWorkArea, MonitorWorkArea, %activeMon%
if (winSizeHeight == "half") {
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop)/2
} else {
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop)/3
}
if (winPlaceHorizontal == "left") {
posX := MonitorWorkAreaLeft
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft)/2
} else if (winPlaceHorizontal == "right") {
posX := MonitorWorkAreaLeft + (MonitorWorkAreaRight - MonitorWorkAreaLeft)/2
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft)/2
} else {
posX := MonitorWorkAreaLeft
width := MonitorWorkAreaRight - MonitorWorkAreaLeft
}
if (winPlaceVertical == "bottom") {
posY := MonitorWorkAreaBottom - height
} else if (winPlaceVertical == "middle") {
posY := MonitorWorkAreaTop + height
} else {
posY := MonitorWorkAreaTop
}
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
#!Up::SnapActiveWindow("top","full","half")
#!Down::SnapActiveWindow("bottom","full","half")
^#!Up::SnapActiveWindow("top","full","third")
^#!Down::SnapActiveWindow("bottom","full","third")
; Numberpad Hotkeys (Landscape)
#!Numpad7::SnapActiveWindow("top","left","half")
#!Numpad8::SnapActiveWindow("top","full","half")
#!Numpad9::SnapActiveWindow("top","right","half")
#!Numpad1::SnapActiveWindow("bottom","left","half")
#!Numpad2::SnapActiveWindow("bottom","full","half")
#!Numpad3::SnapActiveWindow("bottom","right","half")
; Numberpad Hotkeys (Portrait)
^#!Numpad8::SnapActiveWindow("top","full","third")
^#!Numpad5::SnapActiveWindow("middle","full","third")
^#!Numpad2::SnapActiveWindow("bottom","full","third")
@maylortaylor

This comment has been minimized.

maylortaylor commented Nov 8, 2016

Would it possible to add a parameter to the SnapActiveWindow() to tell it which monitor to do the snapping action to?
I have 3 monitors and i'd love to be able to specify which monitor to snap my windows to

@DacioRomero

This comment has been minimized.

DacioRomero commented Oct 6, 2017

@maylortaylor I'm by no means a professional nor experienced AHK scripter, but I think this accomplishes what you wanted.

@Cerothen

This comment has been minimized.

Cerothen commented Nov 22, 2017

For anyone interested I decided to extend this script a bit to incorporate a few features v2.0 (Click Here)

  • Move to next monitor (If moving window to the exact same place as it already is it will go to the same place on the next monitor)
  • Add in some general snaps out of convenience (eg left and right from the number pad)
  • A whole new part of the script based on the original idea, region snapping as dynamically determined by the number pad. (the actual function for it is dynamic SnapActiveWindowAdvanced(anchor, widthUnit, heightUnit, snapGrid := 3,activeMon := 0) and could be used for grids of any size, the 3x3 layout of the number pad met my needs though so I left it at that.
@DanielGGordon

This comment has been minimized.

DanielGGordon commented Jun 12, 2018

Is there anyway to not have the extra space when snapping? I am able to snap to the top half of my screen, but there is a little space around the window. This is what it looks like when snapping to top half and bottom half:

image

I saw this:

SysGet, MonitorWorkArea, MonitorWorkArea, %activeMon%

    if (winSizeHeight == "half") {
        height := (MonitorWorkAreaBottom - MonitorWorkAreaTop)/2

Is MonitorWorkArea simply not "correct"? I remember reading somewhere that Windows 10 behaves differently than Windows 7 in this regard.

Actually I just tested the following: ^+!#F11::WinMove, A,, 0, 0,1430,1280

I tried it, and the result is like this:
image

As you can see, it is not lined up on the left, even though it was snapped to (0,0)

And apparently, this "misalignment" is different from app to app. See this question here: winmove in Windows 10 misalignment

@DanielGGordon

This comment has been minimized.

DanielGGordon commented Jun 13, 2018

@AWMooreCO any idea?

@jondcoleman

This comment has been minimized.

jondcoleman commented Aug 20, 2018

@DanielGGordon I saw the same thing. I don't know why it is but I added a manual pixel adjustment in this fork, which solves the problem for me: https://gist.github.com/jondcoleman/77ea6243e0493f81b1d4fde2bf0d0de0

Edit: Actually, I just realized that it doesn't work for all applications. Seems like there's a difference with some windows vs others. Not sure why.

@jondcoleman

This comment has been minimized.

jondcoleman commented Aug 20, 2018

@jondcoleman

This comment has been minimized.

jondcoleman commented Aug 20, 2018

I updated my script to exclude certain processes for the adjustment. You'd have to maintain that list.

@park-brian

This comment has been minimized.

park-brian commented Oct 4, 2018

It looks like we can use the WinGetPosEx function to determine the offsets that should be applied to the window in order to remove the gaps. Here's a fork that demonstrates this: https://gist.github.com/park-brian/f3f790e559e5145b99bf0f19c7928dd8

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