Hilfe bei GUI Funktion aufrufen bzw Tastendruck senden

  • So nun ist es soweit, ich brauch mal eure Hilfe.
    Ich versuche mich gerade mit GUI's und möchte das er eine Funktion ausführt wenn ich einen Button drücke.

    Spoiler anzeigen
    [autoit]

    HotKeySet("{NUMPAD3}", "_EXIT")

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

    GUICreate("Meine GUI", 400, 300, 1000,350)
    $scriptExit = GUICtrlCreateButton("Close", 250, 250, 60,20)

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

    GUISetState()
    while 1
    $msg = GUIGetMsg() ; Prüft ob eine Aktion in der GUI erfolgte
    Select
    Case $msg = -3
    Send("{NUMPAD3}")
    Case $msg = $scriptExit
    Send("{NUMPAD3}")
    EndSelect
    WEnd

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

    Func _EXIT()
    FileDelete (@TempDir & "\bing.wav")
    Sleep(200)
    MsgBox("","Info", "Programm beendet und geschlossen!")
    Exit 0
    EndFunc

    [/autoit]

    Wenn ich nun Numpad3 drücke wird das File gelöscht und das Programm beendet, selbiges passiert wenn ich das "X" drücke, aber warum nicht wenn ich den "Close"-Button anklicke?
    Auch hatte ich versucht "_Exit()" im Case ausführen zu lassen, aber ohne erfolg.

    Was mache ich falsch und wie kann ich das richtig machen?


    Liebe Grüße und besten Dank
    Chris

    3 Mal editiert, zuletzt von M9_Chris (12. September 2014 um 12:31) aus folgendem Grund: AutoIT Tags statt Code Tags... Jaja Wald und Bäume und so....

  • Ich bin ein Ahnungsloser und kann dir nicht kompetent helfen. Aber damit du eine Rückmeldung bekommst:
    1. Den Hotkey Send("{NUMPAD3}") in den Buttons zu verwenden finde ich lustig.
    2. Bei mir funktioniert ein Klick auf den Close Button genauso wie die anderen Varianten. (Die Funktion wird ausgeführt. Ein File habe ich nicht gelöscht..)

    Kann es sein, dass dies hier nur ein Beispiel für dein Problem ist, du aber das Beispiel nie getestet hast?
    Ansonsten würde ich folgendes vorschlagen: Du hast ja noch Platz in deiner GUI. Mach den Button einfach so groß, dass du ihn auch triffst ;)

    Nur Spaß. Bei mir klappt es jedenfalls.

    Grüße autoiter

  • Hallo M9_Chris,

    wie "autoiter" auch, bin ich ähnlich verwirrt. Naja nicht wirklich verwirrt, doch die Frage ist tatsächlich auf was du hinaus möchtest? Ich versuche es mal auseinander zu nehmen, da du hier 2 Varianten umsetzen kannst bzw. gemixt hast.

    Ich gehe auch davon aus, dass dies ganze ein Test für dich ist, da du dich mit GUIs beschäftigst? Hmmm, okay ...

    HotKeySet:

    Spoiler anzeigen
    [autoit]


    ; ------------------------------------------------------------------------------
    ; Variante 1 - HotKeySet
    ; ------------------------------------------------------------------------------
    ; HotKey und seine Funktion (die aufgerufen werden soll)
    HotKeySet( "{NUMPAD3}", "_EXIT" )

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

    ; GUI mit 2 Buttons
    GUICreate( "Meine GUI", 400, 300, 1000, 350 )
    $scriptExit = GUICtrlCreateButton( "Close", 250, 250, 60, 20 )
    $cBtnInfo = GUICtrlCreateButton( "Info", 320, 250, 60, 20 )
    GUISetState( @SW_SHOW )

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

    ; While, um Events / Aktionen auszuführen bspw.
    While 1
    $eMsg = GUIGetMsg()
    Switch $eMsg
    Case -3, $scriptExit
    ;_EXIT() ; hier passiert jetzt nix
    Case $cBtnInfo
    ;_infoFunction() ; hier passiert jetzt nix
    EndSwitch
    WEnd

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

    ; deine _EXIT()-Funktion
    Func _EXIT()
    FileDelete( @TempDir & "\bing.wav" )
    Sleep( 200 )
    MsgBox( "", "Info", "Programm beendet und geschlossen!" )
    Exit 0
    EndFunc

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

    ; Zusätzliche Beispielfunktion
    Func _infoFunction()
    MsgBox( 64, "Information", "Dies ist eine dummy MsgBox-Meldung!" )
    EndFunc

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

    Kurz zusammenfassend erläutert: Hier wird nur auf den Tastendruck NUM3 reagiert und deine _EXIT()-Funktion ausgeführt. Die GUI wird zwar angezeigt, aber hat mit ihren Buttons keine Event-Eigenschaften. Also das Schließen-X wird nicht funktionieren ebenso wenig wie ESC oder der Close-Button.

    HotKeySet wird unter anderem dafür oft genutzt, an jeder Stelle des Skriptablaufes eine definierte Funktion auszuführen, wenn es vom Benutzer gewollt ist. Gerade wenn man keine GUI hat ist dies sinnvoll. Wenn du aber mit GUIs arbeitest, solltest du lieber die Variante 2 nutzen.

    Dies schließt nicht aus, dass du keine HotKeys in Verbindung mit GUIs nutzen solltest. Doch auf die gleiche Funktion wie in deinem Fall ist etwas sinnlos denke ich.


    Buttons und Funktionen:

    Spoiler anzeigen
    [autoit]


    ; ------------------------------------------------------------------------------
    ; Variante 2 - Buttons und Funktionen
    ; ------------------------------------------------------------------------------
    ; GUI mit 2 Buttons
    GUICreate( "Meine GUI", 400, 300, 1000, 350 )
    $scriptExit = GUICtrlCreateButton( "Close", 250, 250, 60, 20 )
    $cBtnInfo = GUICtrlCreateButton( "Info", 320, 250, 60, 20 )
    GUISetState( @SW_SHOW )

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

    ; While, um Events / Aktionen auszuführen bspw.
    While 1
    $eMsg = GUIGetMsg()
    Switch $eMsg
    Case -3, $scriptExit
    _EXIT() ; jetzt wird diese Funktion auch ausgeführt
    Case $cBtnInfo
    _infoFunction() ; jetzt wird diese Funktion auch ausgeführt
    EndSwitch
    WEnd

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

    ; deine _EXIT()-Funktion
    Func _EXIT()
    FileDelete( @TempDir & "\bing.wav" )
    Sleep( 200 )
    MsgBox( "", "Info", "Programm beendet und geschlossen!" )
    Exit 0
    EndFunc

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

    ; Zusätzliche Beispielfunktion
    Func _infoFunction()
    MsgBox( 64, "Information", "Dies ist eine dummy MsgBox-Meldung!" )
    EndFunc

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

    Kurz zusammenfassend erläutert: Hier wird über die Switch-EndSwitch-Variante die eigentliche Event-Arbeit gemacht. Das "-3" steht für den Standardschließvorgang (ExitBefehl) der GUI. Ich habe dein Select-EndSelect hier nicht verwendet, da du das GUI-Event "$eMsg = GUIGetMsg()" abfragst und du bei Switch-EndSwitch kommasepariert die Controls (Buttons in dem Fall) aufführen kannst. Im Gegensatz zu Select-EndSelect bei dem du immer eine neue Zeile bzw. ein neues Case dafür anlegen müsstest.

    Also "Case -3, $scriptExit" sagt aus, dass beim Standardschließaktionen wie ESC oder Schließen-X die GUI und hier auch das Skript beendet wird, da es ja deine Funktion danach aufruft. Aber auch der Klick auf deinen Close-Button macht das Gleiche.

    Den 2. Button habe ich eingebaut, damit du siehst wie eine weitere Reaktion ablaufen kann. Sprich, es wird eine weitere Funktion aufgerufen.


    ... ich hoffe ich konnte etwas Licht ins Dunkel bringen ;) . Es macht also wenig Sinn diese Varianten (in deinem Fall) zu mixen. Man muss zwar immer im Einzelfall entscheiden, doch dass grundsätzliche Vorgehen für GUIs wäre dann Variante 2.

    Vielen Dank für etwaige Unterstützung (Ideen, Verbesserungsvorschläge, Kritik und Zustimmung).
    Einen angenehmen Tag noch!

    UserIsGrateful 【ツ】

  • Im Normalfall würde ich Anfängern erst später dazu raten sich den sogenannten "OnEventMode" für GUIs anzusehen, allerdings ist er für exakt den in deinem Script gezeigten Anwendungsfall konzipiert, weshalb ich ihn an dieser Stelle nur mal erwähnt haben möchte. Der OnEventMode ist wie der Name schon vermuten lässt ein Modus, in den du dein GUI versetzen kannst. Hast du dies getan brauchst du dich nicht mehr mit GUIGetMsg() und Co. herumzuschlagen. Stattdessen kannst du einfach festlegen "WENN zu irgend einem Zeitpunkt dieser Button gedrückt wird, DANN ruf doch bitte mal diese Funktion X hier auf" und alles andere erledigt Autoit für dich. Aber genug geredet mein kleiner Beispielcode sollte selbsterklärend sein... :)

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3> ; Durch dieses Include können wir weiter unten die Variable $GUI_EVENT_CLOSE verwenden. Dies ist zwar nicht zwingend notwendig (du könntest auch einfach -3 schreiben, was dem Wert der Variable entspricht) allerdings ist es doch viel schöner und leserlicher wenn sofort klar ist um Welches Event es an einer bestimmten Stelle geht. Oder? :P

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

    Opt("GUIOnEventMode",1) ; GUIOnEventMode einschalten (1) da er standardmäßig deaktiviert ist

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

    $hGUI = GUICreate("Meine GUI", 400, 300, 1000,350) ; GUI erstellen
    $hButtonExit = GUICtrlCreateButton("Close", 250, 250, 60,20) ; Button erstellen

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit") ; Wir legen fest was passieren soll, wenn in unserem GUI das Event $GUI_EVENT_CLOSED auftritt. Im zweiten Parameter geben wir den Namen einer Funktion an die im Falle eines Events - hier ein Klick auf das rote X des GUI - automatisch aufgerufen wird.
    GUICtrlSetOnEvent($hButtonExit,"_Exit") ; Mit dem Button verfahren wir genau gleich. "WENN Button gedrückt DANN '_Exit' aufrufen"

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

    GUISetState(@SW_SHOW) ; GUI sichtbar machen

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

    while True ; Endlosschleife
    Sleep(250) ; Da wir den OnEventMode benutzen müssen wir uns hier in der Hauptschleife nicht mehr um das Aufrufen der Funktionen kümmern. :) Das Sleep ist nur zur Entlastung des Prozessors da. (Ohne dieses Sleep würde die Schleife tausende male in der Sekunde durchlaufen)
    WEnd

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

    Func _Exit()
    FileDelete (@TempDir & "\bing.wav")
    MsgBox("","Info", "Programm beendet und geschlossen!")
    Exit
    EndFunc

    [/autoit]

    LG
    Christoph :)

  • Ich grüße euch.
    "autoiter" hat durchaus REcht, dies ist nur ein Codeschnipsel und der Kern meines Problems.
    Ich hatte alles, bis spät in die Nacht noch getestet und rumgeschnipselt, zum Teil funktionierte der Funktionsaufruf, aber halt nur ein mal.
    Neben "_EXIT()" finden in meiner Unit noch andere Funktionen ihren Platz wie z.B. "_setSoundVolume()" und "_showStatus()" etc.
    JEde Funktion hat einen Hotkey und jede soll auch über eine GUI ansprechbar sein bzw. steuerbar sein.
    Es traten, einige für mich sonderbare, Ereignisse auf.
    Der Funktionsaufruf im Case hat fuunktioniert, aber nur ein mal, danach waren alle Buttons und Optionen in der GUI wie tot.
    Da dieses Phänomen bei jedem Button gleich ist, kann es ja nur ein Logikfehler meinerseits sein und eine andere Herangehensweise muss her, ich weis halt nur nicht Welche.
    Wenn mich meine Logik nicht verlassen hat, scheint es als wäre der "OnEventMode" genau das was ich suche, ich werde es gleich mal versuchen umzusetzen.

    Bis hierhin ersteinmal besten Dank, ich werde berichten ob es mein Problem lösen konnte.


    LG
    Chris


    Edit:
    Fast vergessen.
    Warum ich beides mixen möchte ist der, das ich das einfach so will.
    Ein Videoplayer z.B. kann ja auch über die GUI Buttons und Hotkeys gesteuert werden, warum sollte das meine Unit nicht können :D


  • Edit:
    Fast vergessen.
    Warum ich beides mixen möchte ist der, das ich das einfach so will.
    Ein Videoplayer z.B. kann ja auch über die GUI Buttons und Hotkeys gesteuert werden, warum sollte das meine Unit nicht können :D

    Schau dir doch mal den Befehl an:

    [autoit]

    GUISetAccelerators

    [/autoit]

    MfG

    UNPLEASANT SPOILER

    You just lost the game!

  • OnEvent hat egtl nichts mit deinem Problem zu tun. Du hast einfach was zusammengebastelt das zwar funktionieren kann aber sehr umständlich ist.
    Send und Hotkeyset sind einfach hier nicht ideal, aber shadow667 hat ja eh schon eine bessere Lösung gepostet ;)

    Was nicht heißt dass es im OnEventModus nicht geht oder schlechter ist. Es wäre nur anders, aber wenn du es wieder mit Hotkeys machst einfach nicht schön.

  • Hallo M9_Chris, hallo weitere Ideengeber,

    Chris, du kannst deine Mixaktion so machen, wie in meinen Beispielvarianten 1 und 2 aufgeführt. Bzw. kannst du einfach aus der Variante 1 den/die HotKeys mit in Variante 2 übernehmen, dann funktioniert dies genauso, wie du anfangs wolltest (zumindest habe ich dich so verstanden).

    Besser wäre aber:

    Spoiler anzeigen

    OnEventMode wie Christoph54 beschrieben hat zu benutzen, auch wenn dies vielleicht etwas schwieriger zu überblicken ist, wenn du damit noch keine Erfahrungen hast.

    Was ich auch sehr schön finde, aber vielleicht ein wenig zu viel des Guten, ist shadow667s Funktionshinweis GUISetAccelerators().


    Du kannst deine HotKeys und die Buttons natürlich auf die gleichen Funktionen los lassen, wenn es bei deinem Beispiel oder Anwendungszweck so sein muss. Aber GUISetAccelerators() ist wahrscheinlich wirklich die eleganteste Variante.

    Vielen Dank für etwaige Unterstützung (Ideen, Verbesserungsvorschläge, Kritik und Zustimmung).
    Einen angenehmen Tag noch!

    UserIsGrateful 【ツ】

  • Ich grüße euch,
    ich habe es gestern mit

    [autoit]

    GUISetAccelerators

    [/autoit]

    versucht und im ersten Augenblick dachte ich, ich hätte es nun hinbekommen.
    Leider lag ich falsch, aber Versuch macht klug und ich konnte feststellen das die GUI "tot" wird sobald ich einen Button oder einen Hotkey drücke.
    Ich habe auch eine Vermutung was passiert bzw. warum es nicht geht.

    Ich habe oben meine GUI mit Labels Buttons etc. und alle Funktionen (egal wie ich sie in die Buttons zuweise) funktionieren wunderbar bis auf die "_START()", in der Funktion "_START()" befindet sich eine fleißige Whileschleife die nach gegebenheiten sucht und dann entsprechend agiert.
    Die Schleife wird also niemals verlassen, soll sie auch nicht und genau da scheint, mMn. das Problem zu liegen.
    Der Fehler liegt also im Aufbau des Scriptes, ich versuche heute den Aufbau zu ändern, sollte ich scheitern, würde ich euch das Ding hier gerne mal Posten, aber erstmal möchte ich versuchen das alleine zu schaffen.
    Wenn ihr aber mit den schmalen Infos von oben etwas anfangen könnt und Ideen habt, bin ich natürlich offen für etwaige Denkanstöße. ^^

  • Warum befinden sich die Buttons in einer anderen While Schleife..? Versuch das einfach zu vermeiden, denn das ist ganz sicher ein Holzweg. Reicht es nicht, in regelmäßigen Abständen etwa mit AdlibRegister Funktionen aufzurufen, in denen auf die Events geprüft wird?

    Grüße autoiter

  • Da musst du was falsch verstanden haben, die Buttons liegen in keiner Funktion oder Schleife, sie leigen genau da wo sie, laut Tuturials (hier aus dem Forum) liegen und deklariert werden sollen.

    [autoit]

    AdlibRegister

    [/autoit]

    ..scheint Potential zu haben wenn ich die Unit umbaue.

  • Ohne Mist, ich glaube das erste Thema, dass ich verfasst habe, hieß: "Wie der While-Schleife entkommen" oder so.
    Ich hoffe, diese Hilfe-Anfrage war nicht das Tutorial, in dem du das gesehen hast :D

    Grüße autoiter

  • Also grundsätzlich darfst du nicht eine zweite Endlosschleife bauen (schon garnicht in einer Funktion) in der dann deine GuiEvents nicht abgefragt werden.
    Adlibregister kann eine lösung für dich sein. Und zwar müsstest du dazu deine _START() Funktion so umbauen dass sie auch funktioniert wenn du sie immer wieder aufrufst.
    (was auch immer die genau tut^^)
    D.h. statt einer Endlosschleife in der Start Funktion brauchst du eine Start-Funktion die immer wieder per Adlibregister aufgerufen wird.
    In der Startfunktion kannst du ja dann die gegebenheiten prüfen und darauf reagieren.
    Achte aber darauf dass die Start funktion möglichst schnell durchläuft. In jedem fall um einiges schneller als der Zeitwert den du bei Adlibregister angibst

  • Ohne Mist, ich glaube das erste Thema, dass ich verfasst habe, hieß: "Wie der While-Schleife entkommen" oder so.
    Ich hoffe, diese Hilfe-Anfrage war nicht das Tutorial, in dem du das gesehen hast :D

    Öhm, nein.
    Wenn nicht mindestens 90% der Leute ein Tutorial für "gut" befunden haben, wird es eiskalt ignoriert, Halbwissen ist mir zuwieder :D
    Es war ein TuT welches ich auf Y-Tube gefunden hatte und es nach meinen Beitritt hier wiederfand.

    Spoiler anzeigen

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne deine Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklärst du dich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.

    • Offizieller Beitrag

    Etwas sollte man generell beachten, und zwar egal ob MsgLoop-Schleife oder OnEventMode: Die Funktion, die bei einem Event (z.B. Button-Klick) aufgerufen wird oder der Case-Zweig bei der MsgLoop-Schleife darf keine Endlos-Schleife enthalten.
    Man sollte die Funktion oder den Case-Zweig so schnell wie möglich wieder verlassen. Wenn man diesen Punkt beachtet, dann wird auch die GUI immer bedienbar bleiben.
    Will man per Button eine länger dauernde Funktion aufrufen, dann am besten nur eine Variable setzen und in der Endlosschleife (OnEventMode) auf diese Variable prüfen.
    Kleines Beispiel:

    Spoiler anzeigen
    [autoit]


    #include <GUIConstantsEx.au3>
    Opt('GUIOnEventMode', 1)

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

    Global $fStart = False, $iCount = 0

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

    Global $hGui = GUICreate('', 320, 200)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_End')

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

    Global $idCounter = GUICtrlCreateLabel($iCount, 10, 10, 100, 25)
    GUICtrlSetFont(-1, 14, 400, 0, 'Arial', 5)
    Global $idStart = GUICtrlCreateButton('Start', 10, 50, 100, 25)
    GUICtrlSetOnEvent(-1, '_Start')
    Global $idStop = GUICtrlCreateButton('Stop', 10, 90, 100, 25)
    GUICtrlSetOnEvent(-1, '_Stop')

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

    GUISetState()

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

    While Sleep(50)
    If $fStart Then
    $iCount += 1
    GUICtrlSetData($idCounter, $iCount)
    EndIf
    WEnd

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

    Func _End()
    Exit
    EndFunc

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

    Func _Start()
    $fStart = True
    EndFunc

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

    Func _Stop()
    $fStart = False
    EndFunc

    [/autoit]
  • Anhand deines Beispieles, scheint der "Groschen" endlich gefallen zu sein, ich bin zwar noch nicht fertig mit dem Umschreiben, aber erste Tests sind vielversprechend.
    Es dauert noch ein bisschen, bin heute etwas langsam, ich melde mich ob es nun endlich geklappt hat oder nicht.

  • Naja was soll ich sagen?
    Hört selbst:

    Spoiler anzeigen


    Hmmm:

    Spoiler anzeigen

    Vielen lieben herzlichen Dank für eure wunderbare Hilfe.
    Ich konnte dadurch eine Menge lernen und mit dem Gelernten öffnen sich gleich ganz neue Türen, ich bin gespannt was mir noch so einfällt was ich in meiner Unit einbauen kann.

    Ach ja fast vergessen, es war der

    [autoit]

    GUICtrlSetOnEvent()

    [/autoit]

    und vor allem der letzte Post Oscar's der mich auf den richtigen Weg brachten.
    Ihr seid echt klasse, ich freue mich auf Weiteres.
    Ich werde das Thema morgen noch auf "Gelöst" setzen, wenn ich es jetzt täte wäre der Witz weg, man möge mir verzeihen :rolleyes:
    Also nochmals vielen herzlichen Dank


    LG
    Chris