#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
;
Global Const $WM_EXITSIZEMOVE = 0x0232
Global Const $SC_MOVE = 0xF010
Global Const $SC_SIZE = 0xF000
Global $nRange = 20
Global $IsSideWinStick = False ;True for sticking to all visible windows ( it's hangs up CPU).
$hGUI = GUICreate("GUI Stickable!", 280, 150)
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE")
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")
$Stickable_CB = GUICtrlCreateCheckbox("Stickable (to the screen edges)", 20, 20)
GUICtrlSetState(-1, $GUI_CHECKED)
$StickableToAll_CB = GUICtrlCreateCheckbox("Stickable to all windows (High CPU usage !!!)", 20, 40)
GUICtrlCreateLabel("Stick Range:", 20, 93)
$Range_Input = GUICtrlCreateInput($nRange, 90, 90, 40, 20, $ES_READONLY)
$UpDown = GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 80, 5)
GUISetState()
GUICreate("Some extra window", 320, 180, 0, 0)
GUISetState()
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
ExitLoop
Case $Stickable_CB
If GUICtrlRead($Stickable_CB) = $GUI_CHECKED Then
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE")
Else
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "")
GUIRegisterMsg($WM_SYSCOMMAND, "")
GUIRegisterMsg($WM_EXITSIZEMOVE, "")
EndIf
Case $StickableToAll_CB
If GUICtrlRead($StickableToAll_CB) = $GUI_CHECKED Then
$IsSideWinStick = True
Else
$IsSideWinStick = False
EndIf
Case $UpDown
$nRange = GUICtrlRead($Range_Input)
EndSwitch
WEnd
Func WM_WINDOWPOSCHANGING($hWnd, $Msg, $wParam, $lParam)
Local $stWinPos = DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
Local $nLeft = DllStructGetData($stWinPos, 3)
Local $nTop = DllStructGetData($stWinPos, 4)
Local $aCurWinPos = WinGetPos($hWnd)
Local $aWorkArea = _GetWorkingArea()
;Left
If Abs($aWorkArea[0] - $nLeft) <= $nRange Then DllStructSetData($stWinPos, 3, $aWorkArea[0])
;Right
If Abs($nLeft + $aCurWinPos[2] - $aWorkArea[2]) <= $nRange Then DllStructSetData($stWinPos, 3, $aWorkArea[2] - $aCurWinPos[2])
;Top
If Abs($aWorkArea[1] - $nTop) <= $nRange Then DllStructSetData($stWinPos, 4, $aWorkArea[1])
;Bottom
If Abs($nTop + $aCurWinPos[3] - $aWorkArea[3]) <= $nRange Then DllStructSetData($stWinPos, 4, $aWorkArea[3] - $aCurWinPos[3])
If Not $IsSideWinStick Then Return 0
Local $ahWnd = WinList()
Local $aStickWinPos, $XPoint, $YPoint
For $i = 1 To UBound($ahWnd) - 1
If $ahWnd[$i][1] = $hWnd Or Not BitAND(WinGetState($ahWnd[$i][1]), 2) Then ContinueLoop
$aStickWinPos = WinGetPos($ahWnd[$i][1])
If UBound($aStickWinPos) < 3 Then ContinueLoop
$XPoint = $aStickWinPos[0]+15
$YPoint = $aStickWinPos[1]+15
If $XPoint < 0 Then $XPoint = 5
If $YPoint < 0 Then $YPoint = 5
If $aCurWinPos[1] + $aCurWinPos[3] >= $aStickWinPos[1] And $aCurWinPos[1] <= $aStickWinPos[1] + $aStickWinPos[3] Then
;Left
If Abs(($aStickWinPos[0] + $aStickWinPos[2]) - $nLeft) <= $nRange And _
_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
DllStructSetData($stWinPos, 3, $aStickWinPos[0] + $aStickWinPos[2])
;Right
If Abs($nLeft + $aCurWinPos[2] - $aStickWinPos[0]) <= $nRange And _
_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
DllStructSetData($stWinPos, 3, $aStickWinPos[0] - $aCurWinPos[2])
EndIf
If $aCurWinPos[0] + $aCurWinPos[2] >= $aStickWinPos[0] And $aCurWinPos[0] <= $aStickWinPos[0] + $aStickWinPos[2] Then
;Top
If Abs(($aStickWinPos[1] + $aStickWinPos[3]) - $nTop) <= $nRange And _
_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
DllStructSetData($stWinPos, 4, $aStickWinPos[1] + $aStickWinPos[3])
;Bottom
If Abs($nTop + $aCurWinPos[3] - $aStickWinPos[1]) <= $nRange And _
_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
DllStructSetData($stWinPos, 4, $aStickWinPos[1] - $aCurWinPos[3])
EndIf
Next
Return 0
EndFunc
Func WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
Switch BitAND($wParam, 0xFFF0)
Case $SC_SIZE, $SC_MOVE
DllCall("user32.dll", "int", "SystemParametersInfo", "int", 37, "int", 1, "ptr", 0, "int", 2)
EndSwitch
EndFunc
Func WM_EXITSIZEMOVE($hWnd, $Msg, $wParam, $lParam)
Local $Old_Show_Content_Param = RegRead("HKEY_CURRENT_USER\Control Panel\Desktop", "DragFullWindows")
DllCall("user32.dll", "int", "SystemParametersInfo", "int", 37, "int", $Old_Show_Content_Param, "ptr", 0, "int", 2)
EndFunc
Func _GetWindowFromPoint($XPoint, $YPoint)
Local $aResult = DllCall("User32.dll", "hwnd", "WindowFromPoint", "int", $XPoint, "int", $YPoint)
Return $aResult[0]
EndFunc
;===============================================================================
;
; Function Name: _GetWorkingArea()
; Description: Returns the coordinates of desktop working area rectangle
; Parameter(s): None
; Return Value(s): On Success - Array containing coordinates:
; $a[0] = left
; $a[1] = top
; $a[2] = right
; $a[3] = bottom
; On Failure - 0
;
;BOOL WINAPI SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
;uiAction SPI_GETWORKAREA = 48
;===============================================================================
Func _GetWorkingArea()
Local Const $SPI_GETWORKAREA = 48
Local $stRECT = DllStructCreate("long; long; long; long")
Local $SPIRet = DllCall("User32.dll", "int", "SystemParametersInfo", _
"uint", $SPI_GETWORKAREA, "uint", 0, "ptr", DllStructGetPtr($stRECT), "uint", 0)
If @error Then Return 0
If $SPIRet[0] = 0 Then Return 0
Local $sLeftArea = DllStructGetData($stRECT, 1)
Local $sTopArea = DllStructGetData($stRECT, 2)
Local $sRightArea = DllStructGetData($stRECT, 3)
Local $sBottomArea = DllStructGetData($stRECT, 4)
Local $aRet[4] = [$sLeftArea, $sTopArea, $sRightArea, $sBottomArea]
Return $aRet
EndFunc