• Offizieller Beitrag

    Eine kleine UDF zum andocken eines (oder mehrerer) Fenster am Bildschirmrand (bzw. an der Taskleiste).

    Das funktioniert auch mit mehreren Bildschirmen.

    Wenn beim Verschieben des Fensters zusätzlich die rechte Maustaste gedrückt wird, so wird das Docking vorübergehend abgeschaltet und man kann das Fenster auf einen anderen Bildschirm bewegen.

    Version 1.1.0.0 (08.07.2018):

    - Auswertung jetzt mit $WM_WINDOWPOSCHANGING statt $WM_WINDOWPOSCHANGED. Kein Flackern mehr! Danke Bitnugger! :thumbup:

    - Wegen $WM_WINDOWPOSCHANGING funktioniert jetzt das "weiterziehen" mit der Maus nicht mehr, um auf einen anderen Bildschirm zu kommen.

    Deswegen habe ich jetzt einen Hotkey: <CTRL> eingebaut. Wird die CTRL-Taste während des ziehens gedrückt gehalten, so kann man das Fenster auf den anderen Bildschirm ziehen.

    - Es gibt jetzt einen "magnetischen Rahmen" (50 Pixel). Wird das Fenster in diesen Bereich bewegt, wird es an den Rand gezogen.

    Version 1.2.0.0 (08.07.2018):

    - Die UDF nochmal komplett umgestaltet (auf globales 2D-Array). Da waren ein paar blöde Bugs drin. Danke Bitnugger! :thumbup:

    - Eine neue Funktion "_WindowDocking_SetMagneticBorder", mit der man den "MagneticBorder" auf eine beliebige Pixelzahl einstellen kann (siehe Example).

    Version 1.3.0.0 (09.07.2018):

    - Es gab noch einen Fehler, wenn man ein Fenster mit eingeschalteten Docking gelöscht hat (GuiDelete). Dabei wurde die WindowProc nicht wieder auf den alten Wert gesetzt und AutoIt stürzte ab. Behoben!

    - Bei der Array-Verwaltung (globales 2D-Array) war noch ein Fehler drin (falsch dimensioniert). Behoben!

    - Die "CTRL-Tasten-Methode" zum verschieben auf einen anderen Bildschirm habe ich jetzt doch standardmäßig auf die "Zwei-Maustasten-Methode" umgestellt. Das Fenster nur mit der Maus zu verschieben ist doch benutzerfreundlicher. :)

    - In Version v3.3.14.5 von AutoIt gibt es die Konstanten $SM_CXSIZEFRAME und $SM_CYSIZEFRAME, deshalb ist die zusätzliche Definition überflüssig.

    - Das Beispiel öffnet jetzt 3 Fenster und man kann jedes Fenster einzeln konfigurieren.

    Version 1.4.0.0 (11.07.2018):

    - Wenn man ein Docking-Fenster auf einen zweiten Bildschirm geschoben hat und das Fenster minimiert und dann wieder restored hat, dann wurde es auf dem Hauptbildschirm "festgehalten". Behoben!

    - Es gibt eine neue Funktion "_WindowDocking_SetVisible" (damit wird das Fenster auf dem am naechsten liegenden Bildschirm zentriert, wenn sich das Fenster außerhalb des Desktopbereichs befindet).

    - Die Abfrage der rechten Maustaste (zum vorübergehenden ausschalten des Dockings) übernimmt jetzt die Funktion "_RMBpressed()". Im Gegensatz zu "_isPressed" wird damit die virtuelle (statt der physikalischen) rechte Maustaste abgefragt.

    - Das Beispielscript "WindowDocking_Example.au3" um ein Beispiel für die neue Funktion erweitert.

    Version 1.5.0.0 (14.07.2018):
    - Bug in "_WinAPI_CallWindowProc" führte zum hängenbleiben des Script, wenn zusätzlich eine zweite WindowProc-UDF benutzt wurde. Behoben! Vielen Dank, Bitnugger!

    - Meine Funktion zum abfragen der rechten Maustaste war überflüssig, weil es ja "_WinAPI_GetKeyState" gibt. Geändert!

    - Ein paar Code-Optimierungen. Unter anderem eine Funktion erstellt, zum ermitteln des Index anhand des Fensterhandle.

  • Ab Windows 7 gibt es dafür doch bereits das Feature Aero Snap... hier die zugehörigen Registry-Keys.

    AutoIt
    Local $iDockMoving = RegRead('HKEY_CURRENT_USER\Control Panel\Desktop', 'DockMoving'); 1
    Local $iDragHeight = RegRead('HKEY_CURRENT_USER\Control Panel\Desktop', 'DragHeight') ; 4
    Local $iDragWidth  = RegRead('HKEY_CURRENT_USER\Control Panel\Desktop', 'DragWidth') ; 4
    ConsoleWrite('$iDockMoving = ' & $iDockMoving & @CRLF)
    ConsoleWrite('$iDragHeight = ' & $iDragHeight & @CRLF)
    ConsoleWrite('$iDragWidth  = ' & $iDragWidth & @CRLF)

    Allerdings flackert es noch ein wenig, wenn man versucht das Fenster am Bildschirmrand noch weiter zu bewegen.

    Werte besser die Message $WM_WINDOWPOSCHANGING aus und verschiebe das Window nicht selbst, sondern trage bei Bedarf einfach nur die neuen Werte für X und Y in die $tagWINDOWPOS-Struktur ein, denn diese werden im nächsten Schritt verwendet. CX und CY musst du dann natürlich auch anpassen.

    PS: Die Taskleiste muss nicht unbedingt unten sein.

    2 Mal editiert, zuletzt von Bitnugger (8. Juli 2018 um 07:21)

    • Offizieller Beitrag

    Werte besser die Message $WM_WINDOWPOSCHANGING aus und verschiebe das Window nicht selbst, sondern trage bei Bedarf einfach nur die neuen Werte für X und Y in die $tagWINDOWPOS-Struktur ein, denn diese werden im nächsten Schritt verwendet.

    Klasse! So klappt das viel besser. Vielen Dank!

    PS: Die Taskleiste muss nicht unbedingt unten sein.

    Ich werte die Work-Area (ohne Taskleiste) des Monitors aus. Somit spielt es keine Rolle, wo sich die Taskleiste befindet.

    Ich schrieb zwar "unten an der Taskleiste", meinte aber generell an der Taskleiste.

  • - Wegen $WM_WINDOWPOSCHANGING funktioniert jetzt das "weiterziehen" mit der Maus nicht mehr, um auf einen anderen Bildschirm zu kommen.

    Deswegen habe ich jetzt einen Hotkey: <CTRL> eingebaut. Wird die CTRL-Taste während des ziehens gedrückt gehalten, so kann man das Fenster auf den anderen Bildschirm ziehen.

    Du kannst aber auch einfach abfragen, ob sich die linke obere bzw. rechte untere Ecke auf demselben Monitor befindet.

    Zudem sind mir noch zwei Sachen aufgefallen.

    1.) Du erzeugst eine Dummy-GUI und setzt die WinProc-Funktion dann bei _WindowDocking_Remove auf $__g_hDocking_ProcOld. Was passiert, wenn die WinProc-Funktion im Script vor Aufruf von _WindowDocking_Add bereits geändert wurde?

    2.) Du entfernst bei _WindowDocking_Remove immer das zuletzt hinzugefügt Fenster, das kann doch unmöglich richtig sein?!

    Den Wert für den MagneticBorder könntest du auch als optionalen Parameter bei _WindowDocking_Add einbauen und mit in $__g_ahDocking_Gui speichern.

    • Offizieller Beitrag

    Du kannst aber auch einfach abfragen, ob sich die linke obere bzw. rechte untere Ecke auf demselben Monitor befindet.

    Ich will ja aber auch, dass das Fenster am Übergang (zwischen den Monitoren) andockt. Es soll aber auch die Möglichkeit geben das Fenster auf den anderen Monitor zu schieben.

    Deswegen denke ich, dass die Tasten-Methode eigentlich ganz gut ist.

    Zudem sind mir noch zwei Sachen aufgefallen.

    Oh mann! Ja, da hast Du Recht!

    Da passte das Konzept nicht. Ich hatte das Script ursprünglich nur für eine GUI geschrieben und dann als UDF ausgebaut. Ich hab's jetzt nochmal neu überdacht und Deine Einwände berücksichtigt.

    So müsste es jetzt aber passen.

    Den Wert für den MagneticBorder könntest du auch als optionalen Parameter bei _WindowDocking_Add einbauen und mit in $__g_ahDocking_Gui speichern.

    Ja, gute Idee! Vor allem, weil ich jetzt sowieso ein globales 2D-Array benutze, bietet es sich an, das konfigurierbar zu machen.

    Somit ist auch noch eine Funktion "_WindowDocking_SetMagneticBorder" dazugekommen. Damit kann man den Wert nicht nur bei "_WindowDocking_Add" festlegen, sondern auch nachträglich noch ändern.

    Neue Version in Post#1.

    • Offizieller Beitrag

    guck mal, so geht es auch ohne...

    Dein Script funktioniert bei mir nicht korrekt. Wenn sich das Fenster in einer der unteren Ecken befindet, dann kann ich es weiter nach unten bewegen und am linken Rand docken die Fenster gar nicht an.

    Aber wem die Tasten-Methode bei meinem Script nicht gefällt, der kann statt: _IsPressed('11', $__g_hDockingUser32Dll) einfach: _IsPressed('02', $__g_hDockingUser32Dll) eintragen.

    Dann kann man durch zusätzliches drücken der rechten Maustaste das Fenster auf den anderen Bildschirm verschieben. Nur mit der linken Maustaste = Fenster dockt an, linke und rechte Maustaste = Fenster lässt sich weiterschieben.

    • Offizieller Beitrag

    Ich musste die UDF doch noch mal verändern. :)

    Das mit dem "Minimize/Restore" funktionierte nicht auf einen zweiten Bildschirm und die rechte Maustaste war die physikalische rechte Maustaste, was bei Linkshändermäusen unpraktisch ist.

    Außerdem gibt es noch eine neue Funktion "_WindowDocking_SetVisible" (ok, eigentlich ist es eine alte Funktion von mir, aber sie passt hier besser rein).

    So nebenbei habe ich dann noch die Funktionsheader (und ein paar Kommentare) hinzugefügt.

    Neue Version in Post#1.

  • Hm, wozu soll denn Zeile 137 gut sein, wenn doch direkt in der darauf folgenden Zeile 138 das Fenster bewegt wird?

    AutoIt
        _WinAPI_SetWindowPos($hWnd, 0, $iWinX, $iWinY, 0, 0, BitOR($SWP_NOSIZE, $SWP_NOSENDCHANGING)) ; ohne Nachricht an WM_WINDOWPOSCHANGING bewegen
        _WinAPI_SetWindowPlacement($hWnd, $tWinPlmnt) ; jetzt erst die neuen Werte dem Fenster zuweisen

    Edit: Ah, ok, um es nach vorne zu holen...

    In Zeile 144 hast du ein 'c' vergessen...

    ; Description ...: Die neue WindowProc, die dem Dockingfenster bei "_WindowDocking_Add" zugewiesen wird.

    Einmal editiert, zuletzt von Bitnugger (11. Juli 2018 um 20:51)