Skip to content

Instantly share code, notes, and snippets.

@AWMooreCO
Last active April 6, 2024 01:29
Show Gist options
  • Save AWMooreCO/1ef708055a11862ca9dc to your computer and use it in GitHub Desktop.
Save AWMooreCO/1ef708055a11862ca9dc to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link

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
Copy link

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
Copy link

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
Copy link

@AWMooreCO any idea?

@jondcoleman
Copy link

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
Copy link

@jondcoleman
Copy link

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

@park-brian
Copy link

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

@DanielGGordon
Copy link

@park-brian thank you so much that is it! That works great, completely got rid of the issue for me. I added the changes to this script (locally).

Question - how can I:

  • Snap a window to the left third of the screen? I want to split my ultrawide monitor into 3 sections, maybe even 4.

@park-brian
Copy link

@DanielGGordon

Hi Daniel, sorry I couldn't respond to your post earlier! I have updated the script to use a customizable grid (the function name/signature has also been updated). If you want to split your monitor into fourths, you can try this:

; Snap to leftmost fourth of screen (Ctrl + Win + Alt + Numpad)
; 1 row, 4 columns, first row, first column
^#!Numpad1::SnapActiveWindowGrid(1, 4, 1, 1)

; Snap to second fourth of screen
; 1 row, 4 columns, first row, second column
^#!Numpad2::SnapActiveWindowGrid(1, 4, 1, 2)

; Snap to third fourth of screen
; 1 row, 4 columns, first row, third column
^#!Numpad3::SnapActiveWindowGrid(1, 4, 1, 3)

; Snap to rightmost fourth of screen (a bit awkward to use Numpad 4, might want to use regular numbers/right windows/alt)
; 1 row, 4 columns, first row, fourth column
^#!Numpad4::SnapActiveWindowGrid(1, 4, 1, 4)

@abicidandan
Copy link

Hi,

I have an ultrawide monitor 32:9, and would love to be able to split the windows into thirds

Win+Alt + <-- : Left Third
Win+Alt + V/^ : Middle Third
Win+Alt + --> : Right Third

Can this be done?

@park-brian
Copy link

park-brian commented Aug 19, 2019

Yes, you can definitely do this. I have forked this gist at: https://gist.github.com/park-brian/f3f790e559e5145b99bf0f19c7928dd8

The default keybinding for left/middle/right thirds is Win + Alt + Numpad 4/5/6. However, you can easily change this in the keybindings (starting at https://gist.github.com/park-brian/f3f790e559e5145b99bf0f19c7928dd8#file-advancedwindowsnap-ahk-L263)

@glenviewjeff
Copy link

glenviewjeff commented Jan 19, 2020

I forked this and named the new project Hyper Window Snap, adding several enhancements I find very useful. With this new fork, you can:

  • Shrink windows by quarter or half in the direction of the keypad, then "scoot" them around the screen in window sized increments. Allows you to subdivide windows beyond the fixed 4 x 4 quadrants.
  • Split the current Chrome tab into a new window that is placed according to the keypad.

@DanielGGordon
Copy link

For anyone here, I highly recommend taking a look at the @park-brian fork posted above. The script here does not work well in Windows Vista/7/10, you'll see that the windows don't snap all the way to the corner.

@glenviewjeff
Copy link

For anyone here, I highly recommend taking a look at the @park-brian fork posted above. The script here does not work well in Windows Vista/7/10, you'll see that the windows don't snap all the way to the corner.

The fork I made fixes this as well as adds many other new features. Check it out. https://github.com/glenviewjeff/HyperWindowSnap

@rfedoruk
Copy link

rfedoruk commented Oct 4, 2021

If anyone with a vertical monitor needs to be able to snap windows to the lower two-thirds of their portrait screen, you need to add two lines:

^#!Numpad6::SnapActiveWindow("bottom","full","twoThirds")
I put this line at the bottom.

if (winSizeHeight == "third") { height := (MonitorWorkAreaBottom - MonitorWorkAreaTop)/3 } else{ height := ((MonitorWorkAreaBottom - MonitorWorkAreaTop)/3)*2 }

And modified this if statement and it works very well!

@dallascao
Copy link

dallascao commented Jan 13, 2022

The shortcuts do not work when the active window is maxed. To fix this, add the following lines under SnapActiveWindow(winPlaceVertical, winPlaceHorizontal, winSizeHeight) {

   WinGet, isMaxed, MinMax , A
    if (isMaxed ==1) {
        WinRestore, A
    }

@cainnz
Copy link

cainnz commented Apr 17, 2022

is there a way to make the windows snap to work like it does in vim directions? h j k l?

all I would need to do is bind the keybinds at the bottom of the script to whatever keybind I want right? for example

by pressing: Win + Left-Shift + l = would move the windows to the half right of my screen?

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