Fensterdocking an Bildschirmrand

  • Tag auch,
    da ich schon länger nach einer Funktion gesucht habe, die es ermöglicht ein beliebiges Fenster an den Bildschirmrand andocken zu lassen, sobald man dieses Fenster nahe genug daran schiebt, aber nichts gefunden habe, habe ich mir schnell selbst so eine geschrieben und möchte sie hier mal anbieten ;)

    Spoiler anzeigen
    [autoit]

    Func windock($win, $padding = 25)
    $windockpos = WinGetPos($win, "")
    If IsArray($windockpos) Then
    If $windockpos[0] <= $padding Then
    If $windockpos[0] <= $padding And $windockpos[1] <= $padding Then
    WinMove($win, "", 0, 0)
    ElseIf $windockpos[0] <= $padding And $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding Then
    WinMove($win, "", 0, @DesktopHeight - $windockpos[3])
    Else
    WinMove($win, "", 0, $windockpos[1])
    EndIf
    ElseIf $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding Then
    If $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding And $windockpos[1] <= $padding Then
    WinMove($win, "", @DesktopWidth - $windockpos[2], 0)
    ElseIf $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding And $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding Then
    WinMove($win, "", @DesktopWidth - $windockpos[2], @DesktopHeight - $windockpos[3])
    Else
    WinMove($win, "", @DesktopWidth - $windockpos[2], $windockpos[1])
    EndIf
    ElseIf $windockpos[1] <= $padding Then
    WinMove($win, "", $windockpos[0], 0)
    ElseIf $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding Then
    WinMove($win, "", $windockpos[0], @DesktopHeight - $windockpos[3])
    EndIf
    EndIf
    EndFunc

    [/autoit]

    Sie ist zwar nichts besonderes, aber ich finde sie recht nützlich ^^
    Kurzer Hinweis zur Verwendung: Einfach in einer While Schleife die Funktion aufrufen. Der erste Parameter muss das Handle / den Fensternamen des zu steuernden Fensters beinhalten, der zweite ist optional und gibt die Pixelbreite an jeder Randseite des Bildschirms, in welcher das Docking vollzogen werden soll.

    Hier ein Beispiel zur Anwendung:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $gui = GUICreate("Testfenster", 400, 300, -1, 20, Default, $WS_EX_TOPMOST)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    Sleep(1000)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    windock($gui, 30)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func windock($win, $padding = 25)
    $windockpos = WinGetPos($win, "")
    If IsArray($windockpos) Then
    If $windockpos[0] <= $padding Then
    If $windockpos[0] <= $padding And $windockpos[1] <= $padding Then
    WinMove($win, "", 0, 0)
    ElseIf $windockpos[0] <= $padding And $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding Then
    WinMove($win, "", 0, @DesktopHeight - $windockpos[3])
    Else
    WinMove($win, "", 0, $windockpos[1])
    EndIf
    ElseIf $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding Then
    If $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding And $windockpos[1] <= $padding Then
    WinMove($win, "", @DesktopWidth - $windockpos[2], 0)
    ElseIf $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding And $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding Then
    WinMove($win, "", @DesktopWidth - $windockpos[2], @DesktopHeight - $windockpos[3])
    Else
    WinMove($win, "", @DesktopWidth - $windockpos[2], $windockpos[1])
    EndIf
    ElseIf $windockpos[1] <= $padding Then
    WinMove($win, "", $windockpos[0], 0)
    ElseIf $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding Then
    WinMove($win, "", $windockpos[0], @DesktopHeight - $windockpos[3])
    EndIf
    EndIf
    EndFunc

    [/autoit]

    Für meine Zwecke reicht es vollkommen aus, auch wenn man noch ein paar Dinge ändern könnte :P
    Viel Spass damit =)

    PS: Hoffentlich ist das der richtige Bereich dafür "O.o

    Einmal editiert, zuletzt von emsis (19. November 2007 um 21:36)

    • Offizieller Beitrag

    Hi!

    Hab es mal kurz getestet - lustige und sicher ab und zu hilfreiche Funktion :).
    Bei mir (Vista) schiebt er das Fenster minimal über den Rand raus. Außerdem wäre es optimal, wenn er gleich beim Verschieben des Fensters "einrastet", aber ansonsten wirklich nett.

    peethebee

  • Ja das mit dem Einrasten hatte ich mir auch noch überlegt, aber wie gesagt, ich hab das nur mal auf die Schnelle gemacht. Wenn ich da nochmal was dran mache werd ichs per Edit einfügen, ansonsten kann ja auch jemand der Lust hat selbst die Änderung posten ^^

  • Also ich finds voll praktisch :)
    Das werde ich auf jeden Fall öfter benutzen :D

    ____________
    MfG [KdD]Wolf

  • Nabend!
    @ peethebee,

    in dem selben script wir das mit dem "einrasten" während des Verschiebens wohl kaum gehen(zu mindest bei einer einzigen instanz: s.u.), weil beim klick auf die titelleiste das script angehalten wird! Man müsste dann schon ein 2. script starten was die gui aus dem ersten script überwacht, vorzugsweise über commandline damit das 2.script flexibler ist.

    Modifiziertes Script:

    Spoiler anzeigen
    [autoit]


    #cs
    windock by emsis
    modified by DJBaselord
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    #include <GUIConstants.au3>
    If $cmdline[0] <> 0 Then
    Opt("TrayIconHide",1)
    windock($cmdline[1], 30 , True)
    Exit
    EndIf
    $Window_Name = "Testfenster"

    $gui = GUICreate($Window_Name, 400, 300, -1, 20, -1, $WS_EX_TOPMOST)
    GUISetState()
    ShellExecute(@ScriptFullPath,$Window_Name)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func windock($win, $padding = 10, $dock_at_taskbar = False)
    While WinExists($win)

    [/autoit] [autoit][/autoit] [autoit]

    Local $taskbar_Height = 0
    If $dock_at_taskbar = True Then
    #region iwann zur ermittlung der taskbarhöhe von gta - spider übernommen^^
    Opt("WinTitleMatchMode", 4)
    $taskbar_pos = WinGetPos("classname=Shell_TrayWnd")
    $taskbar_Height = $taskbar_pos[3]
    Opt("WinTitleMatchMode", 1)
    #endregion
    Else
    $taskbar_Height = 0
    EndIf
    $windockpos = WinGetPos($win, "")
    If IsArray($windockpos) Then
    If $windockpos[0] <= $padding Then
    If $windockpos[0] <= $padding And $windockpos[1] <= $padding Then
    WinMove($win, "", 0, 0)
    ElseIf $windockpos[0] <= $padding And $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding - $taskbar_Height Then
    WinMove($win, "", 0, @DesktopHeight - $windockpos[3]-$taskbar_Height)
    Else
    WinMove($win, "", 0, $windockpos[1])
    EndIf
    ElseIf $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding Then
    If $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding And $windockpos[1] <= $padding Then
    WinMove($win, "", @DesktopWidth - $windockpos[2], 0)
    ElseIf $windockpos[0] >= @DesktopWidth - $windockpos[2] - $padding And $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding - $taskbar_Height Then
    WinMove($win, "", @DesktopWidth - $windockpos[2], @DesktopHeight - $windockpos[3] - $taskbar_Height)
    Else
    WinMove($win, "", @DesktopWidth - $windockpos[2], $windockpos[1])
    EndIf
    ElseIf $windockpos[1] <= $padding Then
    WinMove($win, "", $windockpos[0], 0)
    ElseIf $windockpos[1] >= @DesktopHeight - $windockpos[3] - $padding - $taskbar_Height Then
    WinMove($win, "", $windockpos[0], @DesktopHeight - $windockpos[3] - $taskbar_Height )
    EndIf
    EndIf
    $Mouse_Position = MouseGetPos()
    $windockpos_end = WinGetPos($win, "")
    $x = $windockpos_end[0]-$windockpos[0]
    $y = $windockpos_end[1]-$windockpos[1]
    MouseMove($Mouse_Position[0]+$x,$Mouse_Position[1]+$y,50000)
    Sleep(100) ; je größer der Wert desto weniger "mangentisch" aber es ruckelt dann auch weniger!
    WEnd
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit]


    Beschreibung:

    Das Script startet sich ein 2. mal aber über commandlineparameter, selbieger übergibt dann den Fensternamen und wird dann von der 2. Instanz zum überwachen des Fensters genutz. Das Script sollte zumindest 1.mal compiliert werden! Hab bis jetzt noch net herausgefunden wie man Parameter an eine .au3 - Datei weitergibt^^

    Naja viel Spaß noch damit

  • für den fall dass es dich interessieren sollte ^^ . da gibt es ein programm: es heißt allsnap. allsnap kann das auch vllt sogar besser...

    hättest es dir in dem fall also leichter machen können. aber der spaß am schreiben zählt ja :)

    sonst kann man eig nur sagen: nice work ;)

    gruß

    • Offizieller Beitrag

    HI,

    Spoiler anzeigen
    [autoit]

    #include<GUIConstantsEx.au3> ;Damit funktioniert es für Beta + Stable..

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Const $Range = 100
    Const $WM_MOVING = 0x0216
    Const $WM_ENTERSIZEMOVE = 0x0231
    Global $taskbarPos = WinGetPos("[CLASS:Shell_TrayWnd]"), $x_start, $y_start

    [/autoit] [autoit][/autoit] [autoit]

    $gui = GUICreate("Attach Window GUI to screen edge", 350, 200)
    GUISetState()
    GUIRegisterMsg($WM_ENTERSIZEMOVE, "On_WM_ENTERSIZEMOVE")
    GUIRegisterMsg($WM_MOVING, "On_WM_MOVING")

    [/autoit] [autoit][/autoit] [autoit]

    While GUIGetMsg() <> $GUI_EVENT_CLOSE
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func On_WM_ENTERSIZEMOVE()
    $aMPos = MouseGetPos()
    $x_start = $aMPos[0]
    $y_start = $aMPos[1]
    EndFunc ;==>On_WM_ENTERSIZEMOVE
    Func On_WM_MOVING($hWnd, $Msg, $wParam, $lParam)
    $aMPos = MouseGetPos()
    $rect = DllStructCreate("long left; long top; long right; long bottom", $lParam)
    $left = DllStructGetData($rect, "left")
    $top = DllStructGetData($rect, "top")
    $right = DllStructGetData($rect, "right")
    $bottom = DllStructGetData($rect, "bottom")
    If $left <= $Range And $aMPos[0] < $x_start Then
    DllStructSetData($rect, "left", 0)
    DllStructSetData($rect, "right", $right - $left)
    EndIf
    If $top <= $Range And $aMPos[1] < $y_start Then
    DllStructSetData($rect, "top", 0)
    DllStructSetData($rect, "bottom", $bottom - $top)
    EndIf
    If $right >= (@DesktopWidth - $Range) And $aMPos[0] > $x_start Then
    DllStructSetData($rect, "right", @DesktopWidth)
    DllStructSetData($rect, "left", (@DesktopWidth - $right) + $left)
    EndIf
    If $bottom >= ($taskbarPos[1] - $Range) And $aMPos[1] > $y_start Then
    DllStructSetData($rect, "bottom", $taskbarPos[1])
    DllStructSetData($rect, "top", ($taskbarPos[1] - $bottom) + $top)
    EndIf
    On_WM_ENTERSIZEMOVE()
    EndFunc ;==>On_WM_MOVING

    [/autoit]

    So long,

    Mega

    Edit GtaSpider: Code gefixt.

  • Da fehlt noch
    Opt("WinTitleMatchMode",4)

    Code
    und [CLASS:Shell_TrayWnd] muss das heißen nicht [CLASS :S hell_TrayWnd]
  • für den fall dass es dich interessieren sollte ^^ . da gibt es ein programm: es heißt allsnap. allsnap kann das auch vllt sogar besser...

    hättest es dir in dem fall also leichter machen können. aber der spaß am schreiben zählt ja :)

    sonst kann man eig nur sagen: nice work ;)

    gruß

    Ich kenne das, aber ich habe den Code hauptsächlich dafür geschrieben um ihn in eigenen Scripten einzusetzen, damit ich nicht extra ein zweites Programm laufen lassen muss ;)

    @Xeno
    Danke dafür, nachdem man es wieder repariert hat tut es auch das, was ich ursprünglich mit meinem Code erreichen wollte :)

  • wie kann ich es so umändern damit das fenster nicht nur oben sondern auch links andockt? damit es also geanu im winkel des desktops ist,?

    mfg joshy

  • Hallo!

    Also bei der Version von Emsis gibt es einen kleinen Haken: Dual Monitor wird nicht unterstützt. Ein Verschieben auf den 2. Moni (in meinem Fall rechts) lässt das Fenster immer wieder zurück nach links springen.

    Solange man mit dem primären zufrieden ist, klappt es wunderbar. Nur mir reicht das leider nicht, ich brauche es rechts :D

  • @Vasco, dann pass das script doch einfach deinen bedürfnissen an. Schau nach den koordinaten ,mit Autoitwindowinfo, die du benötigst und schon dockt es dann am rechten monitor an. ;)
    gruß

  • Dashier habe ich aus dem englischen AutoIt Forum:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $WM_EXITSIZEMOVE = 0x0232
    Global Const $SC_MOVE = 0xF010
    Global Const $SC_SIZE = 0xF000

    [/autoit] [autoit][/autoit] [autoit]

    Global $nRange = 20
    Global $IsSideWinStick = False ;True for sticking to all visible windows ( it's hangs up CPU).

    [/autoit] [autoit][/autoit] [autoit]

    $hGUI = GUICreate("GUI Stickable!", 280, 150)
    GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
    GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE")
    GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")

    [/autoit] [autoit][/autoit] [autoit]

    $Stickable_CB = GUICtrlCreateCheckbox("Stickable", 20, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)

    [/autoit] [autoit][/autoit] [autoit]

    $StickableToAll_CB = GUICtrlCreateCheckbox("Stickable to all windows (High CPU usage)", 20, 40)

    [/autoit] [autoit][/autoit] [autoit]

    $Range_Input = GUICtrlCreateInput($nRange, 20, 70, 40, 20, $ES_READONLY)
    $UpDown = GUICtrlCreateUpdown(-1)
    GUICtrlSetLimit(-1, 80, 5)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    GUICreate("Some extra window", 320, 180, 0, 0)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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()

    For $i = 1 To UBound($ahWnd) - 1
    If $ahWnd[$i][1] = $hWnd Or Not BitAND(WinGetState($ahWnd[$i][1]), 2) Then ContinueLoop

    $aSideWinPos = WinGetPos($ahWnd[$i][1])
    If UBound($aSideWinPos) < 3 Then ContinueLoop

    Local $XPoint = $aSideWinPos[0]+15
    Local $YPoint = $aSideWinPos[1]+15

    If $XPoint < 0 Then $XPoint = 5
    If $YPoint < 0 Then $YPoint = 5

    If $aCurWinPos[1] + $aCurWinPos[3] >= $aSideWinPos[1] And $aCurWinPos[1] <= $aSideWinPos[1] + $aSideWinPos[3] Then
    ;Left
    If Abs(($aSideWinPos[0] + $aSideWinPos[2]) - $nLeft) <= $nRange And _
    WindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
    DllStructSetData($stWinPos, 3, $aSideWinPos[0] + $aSideWinPos[2])

    ;Right
    If Abs($nLeft + $aCurWinPos[2] - $aSideWinPos[0]) <= $nRange And _
    WindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
    DllStructSetData($stWinPos, 3, $aSideWinPos[0] - $aCurWinPos[2])
    EndIf

    If $aCurWinPos[0] + $aCurWinPos[2] >= $aSideWinPos[0] And $aCurWinPos[0] <= $aSideWinPos[0] + $aSideWinPos[2] Then
    ;Top
    If Abs(($aSideWinPos[1] + $aSideWinPos[3]) - $nTop) <= $nRange And _
    WindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
    DllStructSetData($stWinPos, 4, $aSideWinPos[1] + $aSideWinPos[3])

    ;Bottom
    If Abs($nTop + $aCurWinPos[3] - $aSideWinPos[1]) <= $nRange And _
    WindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
    DllStructSetData($stWinPos, 4, $aSideWinPos[1] - $aCurWinPos[3])
    EndIf
    Next

    Return 0
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit]

    Func WindowFromPoint($XPoint, $YPoint)
    Local $aResult = DllCall("User32.dll", "hwnd", "WindowFromPoint", "int", $XPoint, "int", $YPoint)
    Return $aResult[0]
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ;
    ; 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

    [/autoit]


    Funktioniert wunderbar :)