AutoIt Script für Multi-Bildschirm Betrieb

  • Hallo zusammen,

    vielleicht habt Ihr auch schon mal festgestellt das AutoIt neue Fenster immer auf dem Hauptbildschirm des Rechners aufmacht. Also häufig auf dem Bildschirm des Notebooks - was leider nicht immer ideal ist. In AutoIt selber gibt es dazu keine Funktion, die das Verhalten ändert oder ein vorhandenes Fenster auf den aktiven Bildschirm verschiebt.

    Ich habe jetzt eine Funktion geschrieben die bei Aufruf genau Letzteres macht. Ein geöffnetes Fenster wird also auf den Bildschirm verschoben, auf dem sich gerade die Maus befindet. Die relative Position des Fenster auf dem jeweiligen Bildschirm wird beibehalten.


    Version 1.1.2 (deutsch):

    MoveWindowToActiveDisplay.au3

    Version 1.1.1 (englisch dokumentierte UDF Variante):

    MoveWindowToActiveDisplayUdf.au3

    Mit freundlichen Grüßen - PapaPeter

    6 Mal editiert, zuletzt von PapaPeter (15. Mai 2020 um 06:18) aus folgendem Grund: Anhang für deutsche Version (jetzt 1.1.2) bei Beispielcode erweitert um Fehlerhandling bei Benutzung eines Windows Handles

  • Dies ist die aktuelle Version des Quellcodes in der deutsch dokumentierten Variante:

    (enthält Änderungen aufgrund der Beiträge von Bitnugger und

    Beispielcode für Benutzung eines Windows Handles erweitert um Fehlerhandling)

    Mit freundlichen Grüßen - PapaPeter

    5 Mal editiert, zuletzt von PapaPeter (15. Mai 2020 um 06:12) aus folgendem Grund: Beispielcode für Benutzung eines Windows Handles erweitert um Fehlerhandling

    • Offizieller Beitrag

    Vorschlag für folgende Funktion:

  • Hallo BugFix,

    können wir gerne machen, da es für reine Anwender den Code kürzer und schneller macht. Mein Gegenvorschlag eine kommentierte für Einsteiger nachvollziehbare Version und eine optimierte Version zum reinen Einbinden.

    Neue Version angehängt (Berücksichtigt Kommentare von Bitnugger und Änderungen von BugFix):

    Version 1.1.1 (in wesentlichen Änderungen in den UDF-Headern):

    MoveWindowToActiveDisplayUdf.au3

  • Hier noch der Sourcecode in lesbarer Form

    mit Berücksichtigung von Kommmentaren von Bitnugger und Übernahme der Änderungen von BugFix

    Kommentatare in der UDF-Version sind jetzt in englisch

    Spoiler anzeigen

    Mit freundlichen Grüßen - PapaPeter

    3 Mal editiert, zuletzt von PapaPeter (14. Mai 2020 um 10:40) aus folgendem Grund: Kleinere Änderungen in den UDF-Headern

  • If $Debug=1 Then ConsoleWrite(...)

    So kannst du dir das If $Debug=1 Then an zig Stellen sparen:

    AutoIt
    _ConsoleWrite('Dadurch ist der Quellcode nicht nur angenehmer zu lesen, es macht ihn auch deutlich kürzer.' & @CRLF)
    
    Func _ConsoleWrite($sText)
        If $Debug = 1 Then ConsoleWrite($sText)
    EndFunc
  • Als Denkanstoß hier noch ein bisschen unzensierten Senf von mir... ;)

    UDF-Version

    Dann solltest du auch einen originalen UDF-Header benutzen, oder zumindest eine abgespeckte bzw. leicht modifizierte Version.

    Dies hat den Vorteil, dass der CallTip Manager (SciTE Menu Extras -> SciTE Config -> Other Tools -> CallTip Manager) die für den CallTip benötigten Daten dem Header entnehmen kann.

    In SciTE kannst du mit Ctrl+Alt+U einen UDF-Header einfügen, wenn das Caret auf einer Func Zeile steht.

    MoveToActiveDisplay($ParmWindowTitle [,$ParmWindowText] )

    Anhand der Parameter lässt sich zwar ableiten, was die Funktion macht, schöner wäre aber, wenn sich dies bereits anhand des Funktionsnamen ableiten lassen würde.

    MoveWindowToActiveDisplay($ParmWindowTitle [,$ParmWindowText]) ; Besser, aber nicht wirklich korrekt.

    MoveWindowToDisplayFromMousePos($ParmWindowTitle [,$ParmWindowText]) ; Treffender, weil das Display, auf dem sich die Maus befindet, nicht in-/aktiv, sondern lediglich vorhanden ist.

    Das nur der Titel eines Fenster als Parameter akzeptiert wird, ist auch nicht so schön... ein Window-Handle sollte man schon übergeben können und das kannst du auch sehr einfach lösen. Zudem sollte die Überprüfung der Parameter als erstes abgehandelt werden... und wenn alle ok sind, geht es weiter, anderfalls mit Error zurück.

    AutoIt
    Local $hWnd = 'AutoIt Help (v3.3.14.5)'
    If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd)
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, False)

    WinActivate($ParmWindowTitle, $ParmWindowText) ; Kombination WinActivate/WinWaitActive um sicherzustellen das Fenster schon aufgebaut ist,
    WinWaitActive($ParmWindowTitle, $ParmWindowText, 3) ; und dabei aber maximal 3 Sekunden auf Fenster warten muss

    Gar nicht schön!

    Die Funktion soll das Fenster verschieben, falls nötig, es aber nicht aktivieren oder sonstwie andere Dinge machen! Und was spielt es für eine Rolle, wenn das Fenster noch nicht fertig aufgebaut ist?

    Jetzt könnte man noch fragen, was passiert wenn...

    - das Fenster minimiert ist?

    - der Monitor, auf dem das Fenster verschoben werden soll, kleiner ist und das Fenster nicht darauf passt?

    Variablennamen... schöner wäre, wenn du sie entsprechend des Typs deklarierst... z.B. so:

    $ParmWindowTitle ==>> $sParmWindowTitle ; für Strings ($s... für lokale Variablen (die gibt es nur innerhalb von Funktionen!), $g_s... für globale Variablen

    $MousePos ==>> $aMousePos bzw. $g_aMousePos ; für Arrays

    Hier findest du das Wiki dazu: https://www.autoitscript.com/wiki/Best_coding_practices

    So, wenn du mich jetzt noch mags, bist du es selbst schuld! :rofl:

  • Hallo Bitnugger,

    zu Deiner Anmerkung:

    Zitat

    So kannst du dir das If $Debug=1 Then an zig Stellen sparen:

    Ich bin durchaus auch ein Fan, mehrfach benutzte Teile in Funktionen auszulagern, aber für Debugcode mache ich das in der Regel nicht. Mal ehrlich der Kosten-/Nutzen-Aufwand ist in diesem Fall eher gering, vor allem wird es durch den Funktionsnamen '_ConsoleWrite' auch nicht lesbarer.

    Zu Deiner Anmerkung:

    Zitat

    UDF-Version

    Anscheinend benutzte ich eine zu alte Version von Scite4AutoIt3 (bzw. von Jos SciTE Config), meine Version hatte die 'Generate UDF Header Option' noch nicht oder zumindestens waren sie mir nicht bewußt. Ich hatte noch eine sehr frühe Version (unter 1.6, aktuell ist 1.19) von Scite4AutoIt3 installiert und bisher nicht die Notwendigkeit gesehen dies zu ändern. Jetzt habe ich mal aktualisiert. In der reinen "Einbinde" Version meines Codes, die ich vielleicht unsauber "UDF-Version" genannt hatte, war weiterhin alles von Hand kommentiert. Ich werde das demnächst auf eine CallTip Manager kompatible Version umstellen - Danke für den Hinweis.

    Zu Deiner Anmerkung

    Zitat

    Anhand der Parameter lässt sich zwar ableiten, was die Funktion macht, schöner wäre aber, wenn sich dies bereits anhand des Funktionsnamen ableiten lassen würde.

    Sprechende Funktionsnamen sind was Schönes und ich bin ein starker Verfechter der sprechenden Funktionsnamen. Ich finde 'MoveToActiveDisplay'. In der Tat wäre 'MoveWindowToActiveDisplay' wohl besser gewesen und es macht aus meiner Sicht Sinn die Funktion umzubennen.

    Der Name 'MoveWindowToDisplayFromMousePos' macht aus technischer Sicht vielleicht mehr Sinn. Er ist aber erstens aus meiner sich für den Users/Anwenders zu lang (vor allem nicht alle User nutzen Scite und Autoextension) und zweitens wenn ich irgendwo mit der Maus irgendwohin klicke und sich dann ein Fenster öffnet, möchte ich gerne das es sich auf demselben Bildschirm öfnen wo sich gerade hinschaue, also aus meiner Sicht da wo sich gerade die Maus befindet.

    Insofern macht es für mich Sinn den Bildschirm auf dem sich die Maus gerade befindet als aktiven Bildschirm zu bezeichnen. Aus technischer Sicht gibt es keinen Grund einen Bildschirm zu bevorzugen und man könnte es so lassen wie es ist und bräuchte die Funktion gar nicht. Aus Gründen der Usablity gibt aber für mich schon gewichtige Gründe von einem aktiven Bildschirm zu sprechen.

    Zu Deiner Anmerkung:

    Zitat

    ...ein Window-Handle sollte man schon übergeben können...

    Das wäre auch eine Option gewesen und sicher kann man da gerne nachbessern. So wie es in der Routine genutzt wird wäre hier vermutlich ein Windows Handle auch möglich, da es an die entspechen Window... Funktionen weitergeleitet wird - das muß ich aber erst einmal testen (offensichtlich programmiert jeder etwas anders- also gibt es unterschiedliche Needs). Es wird hier nicht der Parameter direkt überprüft, so wie Du es vorschlägst - dann würde tatsächlich nur das eine oder das andere gehen - sondern es wird überprüft ob mit dem Übergabeparametern das Fenster gefunden wird. Aus meiner Sicht ist das hier fehlertoleranter, da es keine unnötigen Beschränkungen einführt und umgekehrt nichts passieren kann wenn hier Müll landet - dann kommt es halt zu dem Fehler, daß das Fenster nicht gefunden werden kann. Ich schaue mal, ob ich eine Lösung finden kann die unser beiden Ansprüchen gerecht wird ;).

    Zu Deiner Anmerkung:

    Zitat

    ... Gar nicht schön! ...

    Hier geht es um die Kombination WinActivate/WinWaitActive. Hast Du mal den orginalen Beispiel-Code laufen lassen? Hier wird ein externes Programm gestartet - nämlich Notepad. Wenn man in AutoIt ein externes Programm startet und direkt danach ein WinExist macht, dann kann man das Problem haben das Notepad zwar gestartet wird, das Fenster aber noch nicht erschienen ist und damit das WinExists fehlschlägt.

    Zugegeben das Problem sollte nicht bei im eigentlichen Sourcecode erzeugten Fenstern auftreten, davon kann ich aber nicht immer ausgehen.

    Was wäre die Alternative gewesen? Man kann auch eine Schleife mit WinExists machen, die benötigt aber zwingend ein Timeout da es sonst unendlich auf ein Fenster wartet das nicht gefunden werden kann (z.B. aufgrund fehlerhafter Parameter) und die Ausführung in der Funktion hängen bleibt. Dies wäre mit einem zusätzlichen optionalen Parameter möglich, der einen Defaultwert enthält.

    Um ehrlich zu sein der Code stand ursprünglich nur im Beispielcode und nicht in der Funktion. Dann hatte ich mir gedacht, das die User obiges verzögertes Verhalten bei Aufruf von externen Programmen nicht berücksichtigen und sich wundern werden, das die Funktion nicht "richtig" arbeitet und habe den Code kurzerhand in die Funktion verschoben.

    Jetzt zu dem Punkt - sollte eine Funktion ein Fenster überhaupt aktivieren wenn es verschoben werden soll? Aus meiner Sicht macht das durchaus Sinn, sonst kann es passieren das das Fenster zwar verschioben wird, aber hinter einem anderen Fenster verschwindet (ist mir auch beim Testen pasiert). Lösung wäre auch hier ein optionaler Parameter, der ein gezieltes Aktivieren/Belassen des Fensters im bisherigen Status erlaubt.

    Ich werde mal überlegen und testen ob ich die beiden obigen Punkte in einer zukünftigen Version berücksichtige.

    Zu Deiner Anmerkung:

    Zitat

    ... Variablennamen... schöner wäre, wenn du sie entsprechend des Typs deklarierst.... Hier findest du das Wiki dazu: https://www.autoitscript.com/wiki/Best_coding_practices ...

    Bitnugger über Best Practices kann man lange streiten und ich weiß das in den AutoIt-Foren, den AutoIt Helpdateien und dem AutIt Wiki wird tatsächlich die Typ-basierte Benennung bevorzugt wird (in der Regel ohne sprechende Namen - als kleine Randnotiz). Die Bevorzugung war aber nicht immer so eindeutig (ich programmiere schon seit über 30 Jahren und auch AutoIt schon ewig - z.B. die deutsche AutoIt2 Hilfe Übersetzung stammte von mir im Alleingang).

    Ich persönlich bin eher ein Anhänger im Beginn des Namens klar zu machen in welchem Kontext die Variable steht (Lokal, Global, Parameter) und wozu sie verwendet wird. Der Typ ist für mich in der Regel aus dem Kontext klar. Bei größeren Projekten (und meine Projekte sind sehr umfangreich) ist mir persönlich das zumindestens wichtiger. Außerdem können Übergabevariablen in AutoIt auch von unterschiedlichen Typ sein wie z.B das Beispiel Winexists zeigt.

    Im Sinne einer einheitlichen Ausrichtung wäre ich bereit den Sourcecode umzuschreiben, aber eigentlich möchte ich auch gerne meinem eigenen Stil treu bleiben.

    Danke für dieAnregungen

    Papa Peter

    P.S.: Vielleicht bin ich unverbesserlich - aber ich hege keine Feindschaft gegen Dich nur weil Du Kritik äußerst - wenn alle gleich Denken wäre es langweilig.

    Mit freundlichen Grüßen - PapaPeter

    4 Mal editiert, zuletzt von PapaPeter (14. Mai 2020 um 13:25)

  • Hallo BigNutter,

    :rofl:

    Du meinst sicher Bitnugger (man sollte schon, als ein Gebot der Höflichkeit, auf die richtige Anrede achten, insbesondere wenn man sich die Mühe macht, so ausführlich zu antworten ;)).

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."