Sign in to follow this  
Followers 0
iCode

Window Dock to Screen Edge

1 post in this topic

#1 ·  Posted (edited)

This function prevents a window from being moved beyond any screen edge, sort of like docking, but there is no 'snap' function. Optionally, you can also prevent another window from overlapping the primary one. This works regardless of the Windows task-bar position/size or auto-hide status.
 

#include-once

; #FUNCTION# ====================================================================================================================
; Name ..........: _WinDock
; Version .......; 1.3.1
; Description ...: Dock a window at any screen edge and, optionally, prevent another window from overlapping the first
; Syntax ........: _WinDock($hWnd1, [$hWnd2])
; Parameters ....: $hWnd1               - Handle to primary window
;                  $hWnd2               - Handle to secondary window (optional)
; Return values .: 1 = No error
;                   set @error = 1, @extended = -1 : $hWnd1 is not a window handle
;                   set @error = 1, @extended = -2 : unable to get taskbar position
;                   set @error = 1, @extended = -3 : unable to get window position of $hWnd1
;                   set @error = 1, @extended = -4 : unable to get window position of (optional) $hWnd2
; Author ........: $iCode
; Modified ......:
; Remarks .......: Works regardless of taskbar position, size and auto-hide status
; Related .......: WinMove
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================

Func _WinDock($hWnd1, $hWnd2 = 0) ; handle of primary window, [handle of secondary window]

    If Not IsHWnd($hWnd1) Then Return SetError(1, -1)

    Local $aWinPos2 = 0, $iMoveWin2 = 0, $overlap, _
            $x1 = Default, $y1 = Default, _
            $x2 = Default, $y2 = Default, $w2 = Default, _
            $scrW = @DesktopWidth, $scrH = @DesktopHeight, _
            $scrLeft = 0, $scrTop = 0

    Local $aTskBarPos = WinGetPos("[CLASS:Shell_TrayWnd]") ; X, Y, W, H
    If @error Then Return SetError(1, -2)

    Local $aWinPos1 = WinGetPos($hWnd1)
    If @error Then Return SetError(1, -3)

    If IsHWnd($hWnd2) Then
        $aWinPos2 = WinGetPos($hWnd2)
        If @error Then
            Return SetError(1, -4)
        EndIf
        $iMoveWin2 = 1
    EndIf

    ; set screen coordinates, less windows taskbar
    If $aTskBarPos[0] <= 0 And $aTskBarPos[3] = $scrH Then ; taskbar on left
        If $aTskBarPos[0] > 0 Then ; taskbar is visible
            $scrLeft = $aTskBarPos[2]
            $scrW -= $aTskBarPos[2]
        EndIf
    ElseIf $aTskBarPos[1] <= 0 And $aTskBarPos[2] = $scrW Then ; taskbar on top
        If $aTskBarPos[1] > 0 Then ; taskbar is visible
            $scrTop = $aTskBarPos[3]
            $scrH -= $aTskBarPos[3]
        EndIf
    ElseIf $aTskBarPos[1] <= 0 And $aTskBarPos[3] = $scrH Then ; taskbar on right
        $scrW = $aTskBarPos[0]
    Else ; taskbar on bottom
        $scrH = $aTskBarPos[1]
    EndIf

    ; positioning on x axis
    If $aWinPos1[0] <= $scrLeft Then
        $x1 = $scrLeft
        If $iMoveWin2 = 1 Then
            If $aWinPos1[2] + $aWinPos2[2] > $scrW Then ; we need to resize the width of $hWnd2
                $x2 = $scrLeft + $aWinPos1[2]
                $w2 = $scrW - $aWinPos1[2]
            ElseIf $aWinPos2[0] < $scrLeft + $aWinPos1[2] Then
                $x2 = $scrLeft + $aWinPos1[2]
            EndIf
        EndIf
    ElseIf $aWinPos1[0] + $aWinPos1[2] >= $scrW Then
        $x1 = ($scrW + $scrLeft) - $aWinPos1[2]
        If $iMoveWin2 = 1 Then
            If $aWinPos1[2] + $aWinPos2[2] > $scrW Then ; we need to resize the width of $hWnd2
                $x2 = $scrLeft
                $w2 = $scrW - $aWinPos1[2]
            ElseIf $aWinPos2[0] + $aWinPos2[2] > $scrW - $aWinPos1[2] Then
                $overlap = ($aWinPos2[0] + $aWinPos2[2]) - ($scrW - $aWinPos1[2])
                $x2 = $scrLeft + ($aWinPos2[0] - $overlap)
            EndIf
        EndIf
    EndIf

    ; positioning on y axis
    If $aWinPos1[1] < $scrTop Then
        $y1 = $scrTop
    ElseIf $aWinPos1[1] + $aWinPos1[3] > $scrH + $scrTop Then
        $y1 = $aWinPos1[1] - (($aWinPos1[1] + $aWinPos1[3]) - ($scrH + $scrTop))
    EndIf

    WinMove($hWnd1, "", $x1, $y1)
    If $iMoveWin2 = 1 Then WinMove($hWnd2, "", $x2, $y2, $w2)

    Return 1

EndFunc

#cs ### EXAMPLE ###
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$Form1 = GUICreate("Form1", 400, 400, @DesktopWidth / 2, @DesktopHeight / 2, -1, BitOR($WS_EX_TOPMOST,$WS_EX_WINDOWEDGE))
$Label1 = GUICtrlCreateLabel("", 0, 0, 400, 200, $SS_CENTER, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetData(-1, "DRAG ME BEYOND A VERTICAL SCREEN EDGE " & @LF & "AND MOVE OTHER WINDOW")
GUICtrlSetCursor (-1, 9)
$Label2 = GUICtrlCreateLabel("", 0, 200, 400, 200, $SS_CENTER, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetData(-1, "DRAG ME BEYOND A VERTICAL SCREEN EDGE " & @LF & "AND DO NOT MOVE OTHER WINDOW")
GUICtrlSetCursor (-1, 9)
GUISetState(@SW_SHOW)

$Form2 = GUICreate("Form2", @DesktopWidth - 150, @DesktopHeight - 150, 75, 50, BitOR($GUI_SS_DEFAULT_GUI,$WS_MAXIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_TABSTOP))
GUISetState(@SW_SHOW)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Label1
            _WinDock($Form1, $Form2)
        Case $Label2
            _WinDock($Form1)
    EndSwitch
WEnd
#ce

last updated: 24-Mar-2014

v1.3.1

* forgot '#include-once'

v1.3

* minor optimizations and some variables renamed

* fixed an oversight where docking of primary window would not occur if the secondary window did not exist

* dumped Return values and set @extended instead

* now sets @error to 1 if something fails

v1.2

* re-wrote most of the function, adding ability to compensate for task-bar position and auto-hide status

Edited by iCode

FUNCTIONS: WinDock (dock window to screen edge) | EditCtrl_ToggleLineWrap (line/word wrap for AU3 edit control) | SendEX (yet another alternative to Send( ) ) | Spell Checker (Hunspell wrapper) | SentenceCase (capitalize first letter of sentences)

CODE SNIPPITS: Dynamic tab width (set tab control width according to window width)

Share this post


Link to post
Share on other sites



Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0