Simple Windows Drag - Easily snap, move and resize windows
-
- Posts: 2
- Joined: 28 Dec 2022, 06:44
Simple Windows Drag - Easily snap, move and resize windows
The goal is to create a script that makes it easy to snap, move and resize windows with a single keystroke and mouse movements.
I’v tried to make those 3 scripts work together :
- Easy Window Dragging KDE style - by Jonny https://www.autohotkey.com/docs/v1/scripts/index.htm#EasyWindowDrag_(KDE)
- Hyper Window Snap - by Andrew Moore and Jeff Axelrod https://github.com/glenviewjeff/HyperWindowSnap
- Middle Mouse Button Gestures (diagonal) - by Drozdman https://www.autohotkey.com/board/topic/87331-middle-mouse-button-gestures-diagonal
It’s all written in Autohotkey V1.1 because of the amount of ressources online and the fact that the originals scripts are all written in this version of the language.
I’m new to coding, so my code is probably not well optimized. But overall, I’m pretty happy with what this piece of code can do.
I’ve created a gitub repository for the project, where you can find more explainations and to make it colaborative !
The link : https://github.com/Tome-Sulmont/SimpleWindowsDrag
[Mod edit: Topic moved from 'Scripts and Functions'.]
I’v tried to make those 3 scripts work together :
- Easy Window Dragging KDE style - by Jonny https://www.autohotkey.com/docs/v1/scripts/index.htm#EasyWindowDrag_(KDE)
- Hyper Window Snap - by Andrew Moore and Jeff Axelrod https://github.com/glenviewjeff/HyperWindowSnap
- Middle Mouse Button Gestures (diagonal) - by Drozdman https://www.autohotkey.com/board/topic/87331-middle-mouse-button-gestures-diagonal
It’s all written in Autohotkey V1.1 because of the amount of ressources online and the fact that the originals scripts are all written in this version of the language.
I’m new to coding, so my code is probably not well optimized. But overall, I’m pretty happy with what this piece of code can do.
I’ve created a gitub repository for the project, where you can find more explainations and to make it colaborative !
The link : https://github.com/Tome-Sulmont/SimpleWindowsDrag
[Mod edit: Topic moved from 'Scripts and Functions'.]
Re: Simple Windows Drag - Easily snap, move and resize windows
Welcome to this AutoHotkey forum!
This board is for people who need help with their scripts. There is a separate board for working scripts and functions.
This board is for people who need help with their scripts. There is a separate board for working scripts and functions.
Re: Simple Windows Drag - Easily snap, move and resize windows
Yes, originalIy I found this post in the v2 scripts and functions forum. Could probably be moved to v1 scripts and functions, based on the description that it is working already.
Edit: Moved.
Re: Simple Windows Drag - Easily snap, move and resize windows
As you should be. This works quite well, although I had to switch F14 to F12 as my keyboard doesn't go above that.But overall, I’m pretty happy with what this piece of code can do.
If it had a way to lock a window in place it would be perfect for my needs. Alas, all known methods apparently don't work with remote (rdp) windows.
This one will be added to my collection for potential alterations down the road, so thank you!!
-
- Posts: 2
- Joined: 28 Dec 2022, 06:44
Re: Simple Windows Drag - Easily snap, move and resize windows
Thanks for moving the thread !
@RDC Feel free to share if you find a way to lock the windows in place, I'm interested.
@RDC Feel free to share if you find a way to lock the windows in place, I'm interested.
-
- Posts: 44
- Joined: 10 Jan 2024, 13:25
Re: Simple Windows Drag - Easily snap, move and resize windows
# Update
Here is the v2 version for those who interested:
# Original post
This is an interesting script.
I tried to convert it to v2. But some functions not working because of the following line:
NumPut('UPtr', 40, monitorInfo)
Functions which trigger with LWin+Numpad-keys and LWin+MButton are not working
Yes, I 've changed F12 to LWin for more convenience
Appreciate your help to fix this.
Here is the v2 version for those who interested:
Code: Select all
; REMOVED: #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode("Input") ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir(A_ScriptDir) ; Ensures a consistent starting directory.
#SingleInstance Force
; TraySetIcon("imageres.dll", "262") ; makes the icon into two window
; Simple Window Drag
; --------------------------------------------------
; version : 1.0.0
; -> Script by Tomé Sulmont (tome.sulmont@laposte.net)
;
; Includes modified versions of :
; - Easy Window Dragging KDE style - by Jonny
; - Middle Mouse Button Gestures (diagonal) - by Drozdman
; - Hyper Window Snap - by Andrew Moore and Jeff Axelrod
;
; https://www.autohotkey.com
;
; The goal with this script is to easily snap, move and resize windows with a single
; key press and a mouse :
; 1) Hold down the LWin key and LEFT-click anywhere inside a window to drag it to
; a new location.
; 2) Hold down LWin and RIGHT-click-drag anywhere inside a window to easily resize it.
; 3) Hold down LWin and MIDDLE-click-drag to perform different actions : maximize,
; always on top or snap a window.
; 4) Hold down LWin and MIDDLE-click without moving to minimize the window under
; the mouse cursor.
;
; Shortcuts :
; LWin + Left Button + Drag : Move a window.
; LWin + Right Button + Drag : Resize a window.
; LWin + Middle Button + Drag Up : Maximize/Restore a window.
; LWin + Middle Button + Drag Down : Always On Top a window.
; LWin + Middle Button + Drag Right : Snap to the Right half.
; LWin + Middle Button + Drag Left : Snap to the Left half.
; LWin + Middle Button + Drag Top Right Corner : Snap to the Top-Right quarter.
; LWin + Middle Button + Drag Top Left Corner : Snap to the Top-Left quarter.
; LWin + Middle Button + Drag Bottom Right Corner : Snap to Bottom-Right quarter.
; LWin + Middle Button + Drag Bottom Left Corner : Snap to the Bottom-Left quarter.
; LWin + Middle Button + Motionless : Minimize a window.
; LWin + Numpad : Snap the active window.
; Note
; --------------------------------------------------
; In my case, LWin is remapped to Caps Lock with PowerToy (because "Capslock::LWin" doesn't work)
If (VerCompare(A_AhkVersion, "1.0.39.00") < 0) {
msgResult := MsgBox("This script may not work properly with your version of AutoHotkey. Continue?", "", 20)
if (msgResult = "No")
ExitApp()
}
; Easy Window Dragging
; --------------------------------------------------
; This is the setting that runs smoothest on my system. Depending on your video card and cpu power, you may want to raise or lower this value.
SetWinDelay(2)
CoordMode("Mouse")
return
; Mouse Gesture
; --------------------------------------------------
LWin & LButton:: {
MouseGetPos(, , &KDE_id) ; Get the window id
; Abort if it's the desktop.
ClassWin := WinGetClass("ahk_id " KDE_id)
if (ClassWin = "WorkerW")
return
; If the window is maximized, restore the initial position
; and size of the window and center the mouse.
KDE_Win := WinGetMinMax("ahk_id " KDE_id)
If KDE_Win {
WinRestore("ahk_id " KDE_id)
WinGetPos(&KDE_WinX1, &KDE_WinY1, &KDE_WinW, &KDE_WinH, "ahk_id " KDE_id)
MouseMove((KDE_WinX1 + (KDE_WinW / 2)), (KDE_WinY1 + (KDE_WinH / 2)), 0)
}
; Move the window.
MouseGetPos(&KDE_X1, &KDE_Y1)
WinGetPos(&KDE_WinX1, &KDE_WinY1, , , "ahk_id " KDE_id)
Loop {
KDE_Button := GetKeyState("LButton", "P") ? "D" : "U" ; Break if button has been released.
if (KDE_Button = "U")
break
MouseGetPos(&KDE_X2, &KDE_Y2) ; Get the current mouse position.
KDE_X2 -= KDE_X1 ; Obtain an offset from the initial mouse position.
KDE_Y2 -= KDE_Y1
KDE_WinX2 := (KDE_WinX1 + KDE_X2) ; Apply this offset to the window position.
KDE_WinY2 := (KDE_WinY1 + KDE_Y2)
WinMove(KDE_WinX2, KDE_WinY2, , , "ahk_id " KDE_id) ; Move the window to the new position.
}
return
}
LWin & RButton:: {
; Get the mouse position and window id,
MouseGetPos(&KDE_X1, &KDE_Y1, &KDE_id)
; Abort if it's the desktop.
ClassWin := WinGetClass("ahk_id " KDE_id)
if (ClassWin = "WorkerW")
return
; Abort if the window is maximized.
KDE_Win := WinGetMinMax("ahk_id " KDE_id)
If KDE_Win
return
; Get the initial window position and size.
WinGetPos(&KDE_WinX1, &KDE_WinY1, &KDE_WinW, &KDE_WinH, "ahk_id " KDE_id)
; Define the window region the mouse is currently in.
; The four regions are Up and Left, Up and Right, Down and Left, Down and Right.
If (KDE_X1 < KDE_WinX1 + KDE_WinW / 2)
KDE_WinLeft := 1
Else
KDE_WinLeft := -1
If (KDE_Y1 < KDE_WinY1 + KDE_WinH / 2)
KDE_WinUp := 1
Else
KDE_WinUp := -1
Loop {
KDE_Button := GetKeyState("RButton", "P") ? "D" : "U" ; Break if button has been released.
if (KDE_Button = "U")
break
MouseGetPos(&KDE_X2, &KDE_Y2) ; Get the current mouse position.
; Get the current window position and size.
WinGetPos(&KDE_WinX1, &KDE_WinY1, &KDE_WinW, &KDE_WinH, "ahk_id " KDE_id)
KDE_X2 -= KDE_X1 ; Obtain an offset from the initial mouse position.
KDE_Y2 -= KDE_Y1
; Then, act according to the defined region.
WinMove(KDE_WinX1 + (KDE_WinLeft + 1) / 2 * KDE_X2, KDE_WinY1 + (KDE_WinUp + 1) / 2 * KDE_Y2, KDE_WinW - KDE_WinLeft * KDE_X2, KDE_WinH - KDE_WinUp * KDE_Y2, "ahk_id " KDE_id) ; X of resized window
KDE_X1 := (KDE_X2 + KDE_X1) ; Reset the initial position for the next iteration.
KDE_Y1 := (KDE_Y2 + KDE_Y1)
}
return
}
LWin & MButton:: {
MouseGetPos(&X1, &Y1, &KDE_id) ; Get the window id
; Abort if it's the desktop.
ClassWin := WinGetClass("ahk_id " KDE_id)
if (ClassWin = "WorkerW")
return
KeyWait("MButton")
MouseGetPos(&X2, &Y2)
MinTime := 50 ; Set` A_TimeSinceThisHotkey
LongTime := 200 ; Set A_TimeSinceThisHotkey to avoid hiting Gesture down by accident
Tolerance := 60 ; Tolerance of the gesture
if (A_TimeSinceThisHotkey > MinTime AND X2 - X1 > 0 AND Y2 - Y1 < 0 AND Abs(X2 - X1) >= Tolerance AND Abs(Y2 - Y1) >= Tolerance) {
GestureTR(KDE_id) ; gesture top/right
}
else if (A_TimeSinceThisHotkey > MinTime AND X2 - X1 > 0 AND Y2 - Y1 > 0 AND Abs(X2 - X1) >= Tolerance AND Abs(Y2 - Y1) >= Tolerance) {
GestureDR(KDE_id) ; gesture down/right
}
else if (A_TimeSinceThisHotkey > MinTime AND X2 - X1 < 0 AND Y2 - Y1 < 0 AND Abs(X2 - X1) >= Tolerance AND Abs(Y2 - Y1) >= Tolerance) {
GestureTL(KDE_id) ; gesture top/left
}
else if (A_TimeSinceThisHotkey > MinTime AND X2 - X1 < 0 AND Y2 - Y1 > 0 AND Abs(X2 - X1) >= Tolerance AND Abs(Y2 - Y1) >= Tolerance) {
GestureDL(KDE_id) ; gesture down/left
}
else if (A_TimeSinceThisHotkey > MinTime AND Y2 - Y1 < 0 AND Abs(Y2 - Y1) >= Tolerance AND Abs(X2 - X1) < Tolerance) {
GestureU(KDE_id) ; gesture up
}
else if (A_TimeSinceThisHotkey > LongTime AND Y2 - Y1 > 0 AND Abs(Y2 - Y1) >= Tolerance AND Abs(X2 - X1) < Tolerance) {
GestureD(KDE_id) ; Gesture down
}
else if (A_TimeSinceThisHotkey > MinTime AND X2 - X1 < 0 AND Abs(X2 - X1) >= Tolerance AND Abs(Y2 - Y1) < Tolerance) {
GestureL(KDE_id) ; gesture left
}
else if (A_TimeSinceThisHotkey > MinTime AND X2 - X1 > 0 AND Abs(X2 - X1) >= Tolerance AND Abs(Y2 - Y1) < Tolerance) {
GestureR(KDE_id) ; gesture right
}
else if ((X1 = X2) and (Y1 = Y2)) {
NoMove(KDE_id) ; gesture no move
}
return
}
; Hyper Window Snap
; --------------------------------------------------
SnapActiveWindow(winPlaceVertical, winPlaceHorizontal, winSizeHeight) {
heightOffset := 7
widthOffset := 15
xOffset := 7
activeWin := WinExist("A")
activeMon := GetMonitorIndexFromWindow(activeWin)
MinMaxState := WinGetMinMax("A")
If (MinMaxState) {
WinRestore("A")
}
MonitorGetWorkArea(activeMon, &MonitorWorkAreaLeft, &MonitorWorkAreaTop, &MonitorWorkAreaRight, &MonitorWorkAreaBottom)
if (winSizeHeight == "half") {
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop) / 2 + heightOffset
} else if (winSizeHeight == "full") {
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop) + heightOffset
} else if (winSizeHeight == "third") {
height := (MonitorWorkAreaBottom - MonitorWorkAreaTop) / 3
}
if (winPlaceHorizontal == "left") {
posX := MonitorWorkAreaLeft - xOffset
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft) / 2 + widthOffset
} else if (winPlaceHorizontal == "right") {
posX := MonitorWorkAreaLeft + (MonitorWorkAreaRight - MonitorWorkAreaLeft) / 2 - xOffset
width := (MonitorWorkAreaRight - MonitorWorkAreaLeft) / 2 + widthOffset
} else {
posX := MonitorWorkAreaLeft - xOffset
width := MonitorWorkAreaRight - MonitorWorkAreaLeft + widthOffset
}
if (winPlaceVertical == "bottom") {
posY := MonitorWorkAreaBottom - height + heightOffset
} else if (winPlaceVertical == "middle") {
posY := MonitorWorkAreaTop + height
} else {
posY := MonitorWorkAreaTop
}
WinMove(posX, posY, width, height, "A")
}
GetMonitorIndexFromWindow(windowHandle) {
; Starts with 1.
monitorIndex := 1
monitorInfo := Buffer(40)
NumPut('UInt', 40, monitorInfo)
if (monitorHandle := DllCall("MonitorFromWindow", "Ptr", windowHandle, "UInt", 0x2))
&& DllCall("GetMonitorInfo", "Ptr", monitorHandle, "Ptr", 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, "UInt") & 1
monitorCount := MonitorGetCount()
Loop monitorCount {
MonitorGet(A_Index, &tempMonLeft, &tempMonTop, &tempMonRight, &tempMonBottom)
; 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
}
; Set actions
; --------------------------------------------------
; Add Title Id to diferanciate diferent multiple instances (explorer or chrome for exemple) ?
GestureTR(KDE_id) { ; gesture top/right
WinActivate("ahk_id " KDE_id) ; Activate the window
SnapActiveWindow("top", "right", "half")
return
}
GestureDR(KDE_id) { ; gesture down/right
WinActivate("ahk_id " KDE_id) ; Activate the window
SnapActiveWindow("bottom", "right", "half")
return
}
GestureTL(KDE_id) { ; gesture top/left
WinActivate("ahk_id " KDE_id) ; Activate the window
SnapActiveWindow("top", "left", "half")
return
}
GestureDL(KDE_id) { ; gesture down/left
WinActivate("ahk_id " KDE_id) ; Activate the window
SnapActiveWindow("bottom", "left", "half")
return
}
GestureU(KDE_id) { ; gesture up
; Toggle between maximized and restored state.
KDE_Win := WinGetMinMax("ahk_id " KDE_id)
If KDE_Win
WinRestore("ahk_id " KDE_id)
Else
WinMaximize("ahk_id " KDE_id)
return
}
GestureD(KDE_id) { ; Gesture down
WinActivate("KDE_id") ; Activate the window
WinSetAlwaysOnTop(-1, "ahk_id " KDE_id)
return
}
GestureL(KDE_id) { ; gesture left
WinActivate("ahk_id " KDE_id) ; Activate the window
SnapActiveWindow("top", "left", "full")
return
}
GestureR(KDE_id) { ; gesture right
WinActivate("ahk_id " KDE_id) ; Activate the window
SnapActiveWindow("top", "right", "full")
return
}
NoMove(KDE_id) { ; gesture no move
WinMinimize("ahk_id " KDE_id) ; Minimize the window
return
}
; Win + Numpad = Snap to conrners for diagonals, or top, bottom, left, right of screen (Landscape)
; --------------------------------------------------
LWin & Numpad1:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("bottom", "left", "half")
return
}
LWin & Numpad2:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("bottom", "full", "half")
return
}
LWin & Numpad3:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("bottom", "right", "half")
return
}
LWin & Numpad4:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("top", "left", "full")
return
}
LWin & Numpad5:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
KDE_Win := WinGetMinMax("A")
If KDE_Win
WinRestore("A")
Else
WinMaximize("A")
return
}
LWin & Numpad6:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("top", "right", "full")
return
}
LWin & Numpad7:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("top", "left", "half")
return
}
LWin & Numpad8:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("top", "full", "half")
return
}
LWin & Numpad9:: {
ClassWin := WinGetClass("A") ; Abort if it's the desktop.
if (ClassWin = "WorkerW")
return
SnapActiveWindow("top", "right", "half")
return
}
# Original post
This is an interesting script.
I tried to convert it to v2. But some functions not working because of the following line:
NumPut('UPtr', 40, monitorInfo)
Functions which trigger with LWin+Numpad-keys and LWin+MButton are not working
Yes, I 've changed F12 to LWin for more convenience
Appreciate your help to fix this.
Last edited by afshindavoudy on 27 Feb 2024, 04:37, edited 1 time in total.
Re: Simple Windows Drag - Easily snap, move and resize windows
Below is a fix for the GetMonitorIndexFromWindow function:
Code: Select all
GetMonitorIndexFromWindow(windowHandle) {
; Starts with 1.
monitorIndex := 1
monitorInfo := Buffer(40)
NumPut('UInt', 40, monitorInfo)
if (monitorHandle := DllCall("MonitorFromWindow", "Ptr", windowHandle, "UInt", 0x2))
&& DllCall("GetMonitorInfo", "Ptr", monitorHandle, "Ptr", 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, "UInt") & 1
monitorCount := MonitorGetCount()
Loop monitorCount {
MonitorGet(A_Index, &tempMonLeft, &tempMonTop, &tempMonRight, &tempMonBottom)
; 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 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)
-
- Posts: 44
- Joined: 10 Jan 2024, 13:25
Re: Simple Windows Drag - Easily snap, move and resize windows
@iPhilip
Works perfectly
Thank you for your help
Works perfectly
Thank you for your help
Re: Simple Windows Drag - Easily snap, move and resize windows
You are welcome!
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)