Easy Window Moving and Resizing

Posted: January 29, 2011 by jellymann in computers, hotkeys, keyboard, mouse, windows

Normally, a window can only be dragged by clicking on its title bar. This script extends that so that any point inside a window can be dragged while holding down a modifier, in this case the Windows key. This is a slightly modified version of this script, and I mentioned it in one of my previous AutoHotkey posts.

#LButton::
CoordMode, Mouse ; Switch to screen/absolute coordinates.
MouseGetPos, EWD_MouseStartX, EWD_MouseStartY, EWD_MouseWin
WinGetPos, EWD_OriginalPosX, EWD_OriginalPosY,,, ahk_id %EWD_MouseWin%
WinGet, EWD_WinState, MinMax, ahk_id %EWD_MouseWin%
if EWD_WinState = 0 ; Only if the window isn't maximized
SetTimer, EWD_WatchMouse, 10 ; Track the mouse as the user drags it.
return

EWD_WatchMouse:
GetKeyState, EWD_LButtonState, LButton, P
if EWD_LButtonState = U ; Button has been released, so drag is complete.
{
SetTimer, EWD_WatchMouse, off
return
}
GetKeyState, EWD_EscapeState, Escape, P
if EWD_EscapeState = D ; Escape has been pressed, so drag is cancelled.
{
SetTimer, EWD_WatchMouse, off
WinMove, ahk_id %EWD_MouseWin%,, %EWD_OriginalPosX%, %EWD_OriginalPosY%
return
}
; Otherwise, reposition the window to match the change in mouse coordinates
; caused by the user having dragged the mouse:
CoordMode, Mouse
MouseGetPos, EWD_MouseX, EWD_MouseY
WinGetPos, EWD_WinX, EWD_WinY,,, ahk_id %EWD_MouseWin%
SetWinDelay, -1 ; Makes the below move faster/smoother.
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY
EWD_MouseStartX := EWD_MouseX ; Update for the next timer-call to this subroutine.
EWD_MouseStartY := EWD_MouseY
return

Gnome windows can also be resized using a modifier+middle mouse button. So to have that functionality in windows, I tweaked the above script a little bit. First, since I’m not very familiar with AHK, I studied the script for a few minutes to find out where all the action lies. I discovered the line that does the actual moving based on all the information collected from user input, etc:

WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY

This means: Move the window (WinMove) that’s under the mouse (ahk_id %EWD_MouseWin%) to position (X,Y), which is the original position of the window (EWD_WinX,EWD_WinY) plus the distance moved by the mouse, which is the position of the mouse (EWD_MouseX,EWD_MouseY) subtracted by the position of the mouse before it was moved (EWD_MouseStartX,EWD_MouseStartY).

Now all I had to do was replace that code with new code that resizes the window instead of moving it. The WinMove function above is taking three arguments, the window to be moved, X and Y. To resize a window, all one has to do is add width and height at the end of the function, so it would be something like this:

WinMove, window, x, y, width, height

The tricky thing about resizing is that the window must resize in a different direction depending on what region of the window the mouse is in. The following image shows where these regions are:

Basically, the window is cut into thirds vertically, then the two side regions are cut into thirds again horizontally, and the center is cut in half horizontally. I used a bunch of nested if-statements to check which region the mouse cursor is and then move/resize the window accordingly. I’m not sure if it is the best way, but it works. Here is that part of the script:

if (EWD_MouseX-EWD_WinX) <= (EWD_WinW/3)
{
if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)
{
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY, EWD_WinW + EWD_MouseStartX - EWD_MouseX, EWD_WinH + EWD_MouseStartY - EWD_MouseY
}
else if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)*2
{
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, , EWD_WinW + EWD_MouseStartX - EWD_MouseX,
}
else
{
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, , EWD_WinW + EWD_MouseStartX - EWD_MouseX, EWD_WinH + EWD_MouseY - EWD_MouseStartY
}
}
else if (EWD_MouseX-EWD_WinX) <= (EWD_WinW/3)*2
{
if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/2)
{
WinMove, ahk_id %EWD_MouseWin%,,, EWD_WinY + EWD_MouseY - EWD_MouseStartY,, EWD_WinH + EWD_MouseStartY - EWD_MouseY
}
else
{
WinMove, ahk_id %EWD_MouseWin%,,,,, EWD_WinH + EWD_MouseY - EWD_MouseStartY
}
}
else
{
if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)
{
WinMove, ahk_id %EWD_MouseWin%,,, EWD_WinY + EWD_MouseY - EWD_MouseStartY, EWD_WinW + EWD_MouseX - EWD_MouseStartX, EWD_WinH + EWD_MouseStartY - EWD_MouseY
}
else if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)*2
{
WinMove, ahk_id %EWD_MouseWin%,,, , EWD_WinW + EWD_MouseX - EWD_MouseStartX,
}
else
{
WinMove, ahk_id %EWD_MouseWin%,,, , EWD_WinW + EWD_MouseX - EWD_MouseStartX, EWD_WinH + EWD_MouseY - EWD_MouseStartY
}
}

The second thing I changed what what mouse button to use. There are two places where this has to change:

The first line #LButton:: must be changed to #MButton:: to use the middle button for resizing.

Then, a few lines down, after EWD_WatchMouse:, there is the line which checks if the mouse button is down: GetKeyState, EWD_LButtonState, LButton, P. All we do is change LButton to MButton, so it looks like this: GetKeyState, EWD_LButtonState, MButton, P. I didn’t bother with changing EWD_LButtonState because that’s just a variable name, and when I did try change it, and all other instances of it, the script stopped working, so I just left it.

And here is the finished script:
[UPDATE] This script doesn’t work with the Easy Window Move script unless it is separate. My next post has a simple fix for that.

#MButton::
CoordMode, Mouse ; Switch to screen/absolute coordinates.
MouseGetPos, EWD_MouseStartX, EWD_MouseStartY, EWD_MouseWin
WinGetPos, EWD_OriginalPosX, EWD_OriginalPosY,,, ahk_id %EWD_MouseWin%
WinGet, EWD_WinState, MinMax, ahk_id %EWD_MouseWin%
if EWD_WinState = 0 ; Only if the window isn't maximized
SetTimer, EWD_WatchMouse, 10 ; Track the mouse as the user drags it.
return

EWD_WatchMouse:
GetKeyState, EWD_LButtonState, MButton, P
if EWD_LButtonState = U ; Button has been released, so drag is complete.
{
SetTimer, EWD_WatchMouse, off
return
}
GetKeyState, EWD_EscapeState, Escape, P
if EWD_EscapeState = D ; Escape has been pressed, so drag is cancelled.
{
SetTimer, EWD_WatchMouse, off
WinMove, ahk_id %EWD_MouseWin%,, %EWD_OriginalPosX%, %EWD_OriginalPosY%
return
}
; Otherwise, reposition the window to match the change in mouse coordinates
; caused by the user having dragged the mouse:
CoordMode, Mouse
MouseGetPos, EWD_MouseX, EWD_MouseY
WinGetPos, EWD_WinX, EWD_WinY, EWD_WinW, EWD_WinH, ahk_id %EWD_MouseWin%
SetWinDelay, -1 ; Makes the below move faster/smoother.
if (EWD_MouseX-EWD_WinX) <= (EWD_WinW/3)
{
if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)
{
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, EWD_WinY + EWD_MouseY - EWD_MouseStartY, EWD_WinW + EWD_MouseStartX - EWD_MouseX, EWD_WinH + EWD_MouseStartY - EWD_MouseY
}
else if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)*2
{
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, , EWD_WinW + EWD_MouseStartX - EWD_MouseX,
}
else
{
WinMove, ahk_id %EWD_MouseWin%,, EWD_WinX + EWD_MouseX - EWD_MouseStartX, , EWD_WinW + EWD_MouseStartX - EWD_MouseX, EWD_WinH + EWD_MouseY - EWD_MouseStartY
}
}
else if (EWD_MouseX-EWD_WinX) <= (EWD_WinW/3)*2
{
if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/2)
{
WinMove, ahk_id %EWD_MouseWin%,,, EWD_WinY + EWD_MouseY - EWD_MouseStartY,, EWD_WinH + EWD_MouseStartY - EWD_MouseY
}
else
{
WinMove, ahk_id %EWD_MouseWin%,,,,, EWD_WinH + EWD_MouseY - EWD_MouseStartY
}
}
else
{
if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)
{
WinMove, ahk_id %EWD_MouseWin%,,, EWD_WinY + EWD_MouseY - EWD_MouseStartY, EWD_WinW + EWD_MouseX - EWD_MouseStartX, EWD_WinH + EWD_MouseStartY - EWD_MouseY
}
else if (EWD_MouseY-EWD_WinY) <= (EWD_WinH/3)*2
{
WinMove, ahk_id %EWD_MouseWin%,,, , EWD_WinW + EWD_MouseX - EWD_MouseStartX,
}
else
{
WinMove, ahk_id %EWD_MouseWin%,,, , EWD_WinW + EWD_MouseX - EWD_MouseStartX, EWD_WinH + EWD_MouseY - EWD_MouseStartY
}
}
EWD_MouseStartX := EWD_MouseX ; Update for the next timer-call to this subroutine.
EWD_MouseStartY := EWD_MouseY
return

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s