Schleifenabbruch nur über HotKey möglich

  • Hallo zusammen,

    wie im Header bereits erwähnt, bekomme ich meine Routine nur über die HotKey Variante gestoppt, nicht über das Menü oder einen Button. Leider habe ich nicht die leiseste Ahnung, warum das so nicht möglich ist. Vielleicht findet jemand von Euch meinen Fehler, danke im Vorraus.

    Gruß

    Einmal editiert, zuletzt von SOLVE-SMART (15. Mai 2025 um 10:57)

  • Ja das ist wirklich etwas tricky in diesem Fall.
    Klären wir erstmal das Warum:
    Wenn man einen Button drückt, dann löst dieser ein bestimmtes Event aus und dieses kommt in eine Art Warteschlange.
    Wenn man dann GuiGetMsg() aufruft, liest es diese Warteschlange aus und gibt das Event zurück und mit diesem kann man dann entsprechend darauf reagieren.

    Bei dir passiert nun folgendes: Du drückst den Start-Menü-Button, das Event $gm_Menu_run wird abgefeuert und in deiner Message-Loop wird nun GUIGetMsg() aufgerufen.
    Dieses findet nun das Event $gm_Menu_run und gibt es zurück. Darauf reagierst du in deinem Code damit, dass die Funktion _startRoutine() aufgerufen wird.

    Nun befinden wir uns in der Funktion _startRoutine().
    Und da wir uns in einer Endlosschleife befinden, kommen wir da erstmal nicht heraus.
    Wenn man nun den Stopp-Button drückt, dann wird das Event $gB_Button1 gefeuert.
    Das Problem: Niemand schaut nun nach ob Events in der Warteschlange stehen, denn GuiGetMsg() wird nicht mehr aufgerufen.
    Das würde erst passieren wenn die Funktion _startRoutine() beendet wird, denn dann befinden wir uns wieder in der Message-Loop.

    HotkeySet macht das hingegen anders. Es setzt nicht das Event in die Schlange sondern reagiert direkt darauf.
    Daher funktioniert das und die GUI-Events nicht.

    Es gibt (das sind zumindest die Variante, welche mir einfallen) da nun 2 Möglichkeiten:

    1. GuiGetMsg() muss auch in der _startRoutine()-Funktion kontinuierlich abgefragt werden.
    2. Auf den GuiOnEvent()-Modus wechseln. Das klingt erstmal einleuchtender, hat aber auch einen Haken - dazu später mehr.

    Variante 1 - GuiGetMsg() in der _startRoutine():

    Das GuiGetMsg() muss in die Schleife von startRoutine() mit hinein. Da die Events aber nur eine bestimmte Lebenszeit in der Schlange haben, kann es passieren, dass wenn sie erst nach dem 1s-Sleep aufgerufen wird, dass das Event dann schon wieder weg ist.
    Daher muss GuiGetMsg() auch während dieser Sekunde permanent abgefragt werden.

    Ich habe das mal folgendermaßen umgesetzt:

    Variante 2 - OnEvent-Modus:

    Die Idee dahinter ist, dass der OnEvent-Modus Funktionen ähnlich wie Hotkeyset aufruft und daher ohne explizite Event-Abfragen funktioniert.
    Das heißt man verknüpft die Events einfach mit den Funktionen und fertig.

    Problem: Auch der OnEvent-Modus arbeitet mit einer Art Warteschlange. Und er arbeitet erst das nächste Event ab, wenn die Funktion, welche durch das vorherige Event aufgerufen wurde beendet wurde.
    Das heißt wir stehen eigentlich wieder vor dem selben Problem.
    Eine Idee hierzu wäre es, den Aufruf von _startRoutine() möglichst kurz zu halten.
    Ich habe das umgesetzt indem diese einfach nur ein AdlibRegister initiiert und dann sich wieder beendet.
    Auf diese Art können dann die weiteren Events bearbeitet werden.
    Der Code ist dann evtl. etwas übersichtlicher: