Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > AutoIt
You last visited: Today at 11:50

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



GUI mit funktionsfähigen Buttons

Discussion on GUI mit funktionsfähigen Buttons within the AutoIt forum part of the Coders Den category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: May 2008
Posts: 167
Received Thanks: 41
GUI mit funktionsfähigen Buttons

heyho,

beim Umbauen meines Scriptes wollte ich diesem gleich ein nettes GUI verpassen - allerdings komme ich in Bezug auf die Buttons irgendwie nicht weiter.

Normaler GUI-Aufbau:
Code:
While 1
   $nMsg = GUIGetMsg()
   Switch $nMsg
      Case $GUI_EVENT_CLOSE
         Exit
      Case $btnStart
         While 1
            $nMsg = GUIGetMsg()
            ConsoleWrite($nMsg & @CRLF)
            Sleep(2000)
         WEnd
      Case $btnStop
         Exit
   EndSwitch
WEnd
Der Code sollte an sich selbsterklärend sein,
GUIOnEventMode ist hierbei nicht aktiviert.

Das Problem ist: der Button $btnStop wird erst ausgeführt, sobald die Schleife beendet ist - was bei einem Bot ja eigentlich möglichst nie passieren sollte, da dies eine Benutzerinteraktion erfordert.

Versuche ich nun "zwischendurch den Button-Status" abzufragen (siehe Case $btnStart), gelingt dies ebenfalls nicht: Hier wird 0, -8 und im Anschluss nur noch -11 ausgegeben - unabhängig davon, ob ich irgendeinen Button anklicke.

Zum Schluss habe ich es mit GUIOnEventMode versucht (der Sinn dieser Option erschließt sich mir absolut nicht)

Code:
Opt("GUIOnEventMode", 1)
$btnStart = GUICtrlCreateButton("Start", 16, 158, 417, 33)
GUICtrlSetOnEvent($btnStart, "_Start")
$btnStop = GUICtrlCreateButton("Stop", 16, 208, 417, 33)
GUICtrlSetOnEvent($btnStop, "_Exit")
GUISetState(@SW_SHOW)

While 1
	Sleep(100)
WEnd

Func _Start()
	For $i = 1 To 5
		; do something ...
		Sleep(2000)
	Next
EndFunc

Func _Exit()
	Exit
EndFunc
Auch hier reagieren die Buttons erst, sobald die Schleife beendet ist (anhand dieses Beispiels nach ca. 10sec, innerhalb einer Endlosschleife nie).

Kann mir jemand sagen, wie man unter diesen Umständen einen Funktionierenden Stop / Pause-Button in den Code einbringen kann?
Selbst ohne schleife würde dies kaum sinnvoll funktionieren, da ein Durchgang bei meinem aktuellen Projekt ca. 30sec - 10min dauern kann - und wenn man da zwischendrin auf Pause klickt, dann soll das Script auch pausieren und nicht erst 10 Minuten später.

Die einzige sinnvolle Alternative, die ich momentan sehe sind hotkeys, allerdings möchte ich die Steuerung eigentlich schon über das GUI managen können,
demnach hoffe ich, dass ihr bessere Ideen habt
nofuture is offline  
Old 08/15/2014, 16:35   #2
 
alpines's Avatar
 
elite*gold: 60
Join Date: Aug 2009
Posts: 2,256
Received Thanks: 815
Ich glaube das Problem liegt an dem Sleep(2000) in dem Case $btnStart.
Du solltest maximal 50-100 (100 ist schon extrem) ms sleepen um User-Inputs noch gut abfangen zu können. Ansonsten landen sie im Schredder.
alpines is offline  
Old 08/15/2014, 16:52   #3
 
elite*gold: 0
Join Date: May 2008
Posts: 167
Received Thanks: 41
Jein, im Schredder landen sie nicht,
beispielsweise im 2. Code (mit der For-Schleife) wird erkannt, wenn der Button geklickt wurde, sobald die For-Schleife beendet ist.

Wenn der Anwender den Start-Button betätigt, müssen ja auch ersteinmal einige Funktionen ausgeführt werden - wie bereits geschrieben im richtigen Script würden erstmal zwischen 30sec und 10min funktionen ausgeführt, bis der Schleifendurchgang erledigt ist.

Es muss doch ne möglichkeit geben, ähnlich wie bei HotKeySet, direkt einen interrupt zu senden, wenn ein Button angeklickt wurde?
nofuture is offline  
Old 08/15/2014, 18:17   #4
 
butter123's Avatar
 
elite*gold: 95
Join Date: May 2011
Posts: 982
Received Thanks: 189
nein mit buttons gibts da keine direkte möglichkeit.
einzige möglichkeit ist, die lange schleife zu unterteilen, nach dem ersten teil wieder zurück auf die grundschleife srpingen, guigetmsg abfragen und falls button nicht gedrückt wurde mit dem 2. teil weiter zu machen.
butter123 is offline  
Old 08/15/2014, 18:47   #5
 
lolkop's Avatar
 
elite*gold: 280
Join Date: May 2007
Posts: 2,818
Received Thanks: 3,483
Man benutzt in jedem singlethreaded Program nur EINE Hauptschleife.

Über Zustandsvariablen, bzw Schalter kann man dann beliebig in Sombination mit Timern Events in ihr auslösen.

beispiel:
Code:
Dim $action[2], $text[2]=["Start","Stop"]
GUICreate("Gui", 200, 50, Default, Default, 0x10C80000)
$button = GUICtrlCreateButton($text[$action[0]], 0, 0, 200, 50)

While True
	Switch GUIGetMsg()
		Case -3
			Exit
		Case $button
			$action[0] = Not $action[0]
			GUICtrlSetData($button, $text[$action[0]])
	EndSwitch
	If $action[0] And TimerDiff($action[1]) >= 1000 Then
		ConsoleWrite("Diese Aktion wird alle 1000ms ausgeführt und blockiert dabei NICHT das Script"&@CRLF)
		$action[1] = TimerInit()
	EndIf
WEnd
Hier ist $action[0] der Zustand und $action[1] übernimmt die Timer funktion für den Zustand $action[0]. Wann immer der Zustand Wahr(1) ist und der Timer eine zeit von 1000ms überschreitet, wird unter der GuiGetMsg() Abfrage noch eine aktion ausgeführt.

Wenn der Gui button genutzt wird, wird einfach nur der Zustand gewechselt und der Text automatisch neu gesetzt. ist der Zustand $action[0] = Wahr (1), bzw wenn die Aktion gerade ausgeführt wird, wird der Text des Buttons auf "Stop" gesetzt. Ist der Zustand hingegen False (0), bzw die Aktion läuft gerade nicht, so wird der Text des Buttons auf "Start" gesetzt.


PS: Sämtliche Funktionen die ein Sleep oder Wait im Namen enthalten, blockieren das gesamte Script und somit auch alle laufenden Abfragen und sollten möglichst nie benutzt werden.
lolkop is offline  
Thanks
2 Users
Old 08/15/2014, 21:57   #6
 
elite*gold: 0
Join Date: May 2008
Posts: 167
Received Thanks: 41
heyho,
erstmal danke für den Tipp mit den Timern

Grundlegend habe ich dem Code (glaube ich zumindest, muss damit nachher erst nen bisschen rumprobieren) annährend verstanden.
Die Problematik der Sleeptimes habe ich grundlegend auch verstanden,
jedoch ist die Frage, ob das Script nicht deutlich ressourcenlastiger wird, wenn ich nach jeder "Aktion" zunächst "ins Hauptmenü zurückkehre und dann abfragen muss, wo bin ich eigentlich und was ist als nächstes zu tun".

Mal ein kleines Beispiel meines Programms:
Es gibt ~50 verschiedene Aufgaben (random), welche der Aufgaben nun gemacht werden muss ermittle ich über ImageSearch.

Bei jeder einzelnen dieser Aufgaben gibt es spezielle Dinge zu tun,
in kleinen klick- oder drück-aktionen wahrscheinlich im Schnitt so 10 Aktionen mit verschiedenen Zuständen.

Hierfür müsste das Script dann natürlich jedes Mal eine ziemlich große Abfrage durchlaufen.

Denkst du, dass es unter den Voraussetzungen immernoch bevorzugt Timer verwendet werden sollten?
nofuture is offline  
Old 08/16/2014, 08:18   #7
 
lolkop's Avatar
 
elite*gold: 280
Join Date: May 2007
Posts: 2,818
Received Thanks: 3,483
Quote:
Originally Posted by nofuture View Post
heyho,
erstmal danke für den Tipp mit den Timern

Grundlegend habe ich dem Code (glaube ich zumindest, muss damit nachher erst nen bisschen rumprobieren) annährend verstanden.
Die Problematik der Sleeptimes habe ich grundlegend auch verstanden,
jedoch ist die Frage, ob das Script nicht deutlich ressourcenlastiger wird, wenn ich nach jeder "Aktion" zunächst "ins Hauptmenü zurückkehre und dann abfragen muss, wo bin ich eigentlich und was ist als nächstes zu tun".

Mal ein kleines Beispiel meines Programms:
Es gibt ~50 verschiedene Aufgaben (random), welche der Aufgaben nun gemacht werden muss ermittle ich über ImageSearch.

Bei jeder einzelnen dieser Aufgaben gibt es spezielle Dinge zu tun,
in kleinen klick- oder drück-aktionen wahrscheinlich im Schnitt so 10 Aktionen mit verschiedenen Zuständen.

Hierfür müsste das Script dann natürlich jedes Mal eine ziemlich große Abfrage durchlaufen.

Denkst du, dass es unter den Voraussetzungen immernoch bevorzugt Timer verwendet werden sollten?
Mit einem clever gestaltetem Code lassen sich selbst theoretisch unenedlich erweiterbare Aufgaben relativ leicht und sauber verwalten.
Sobald man jedoch anfängt mit einer dynamischen Menge an Aufgaben zu arbeiten, wird das Arbeiten mit Arrays und verschachtelten Schleifen unumgänglich.

Beispiel:
Code:
Dim $action[1][5]=[[0,4]] ;[id][text,delay,control,status,timer]
Dim $btnText[2]=["Start","Stop"], $statusText[2]=["pausiert","läuft"]
$guiMain = GUICreate("Gui", 300, 120, Default, Default, 0x10C80000)
$lvActions = GUICtrlCreateListView("Text|Delay|Status", 0, 0, 250, 100)
$btnDel = GUICtrlCreateButton("Del", 250, 0, 50, 20)
$btnStart = GUICtrlCreateButton($btnText[0], 250, 20, 50, 80)
$btnAdd = GUICtrlCreateButton("Add", 250, 100, 50, 20)
$ipText = GUICtrlCreateInput("Dein Text", 0, 100, 125, 20)
$ipDelay = GUICtrlCreateInput("1000", 125, 100, 125, 20, 0x2000)

While True
	$msg = GUIGetMsg()
	Switch $msg
		Case -3
			Exit
		Case $btnStart
			For $i=1 To $action[0][0]
				If GUICtrlRead($lvActions)=$action[$i][2] Then
					$action[$i][3] = Not $action[$i][3]
					GUICtrlSetData($action[$i][2], "||"&$statusText[$action[$i][3]])
					GUICtrlSetData($btnStart, $btnText[$action[$i][3]])
					ExitLoop
				EndIf
			Next
		Case $btnAdd
			$action[0][0] += 1
			ReDim $action[$action[0][0]+1][$action[0][1]+1]
			$action[$action[0][0]][0]=GUICtrlRead($ipText)
			$action[$action[0][0]][1]=GUICtrlRead($ipDelay)
			$action[$action[0][0]][2]=GUICtrlCreateListViewItem($action[$action[0][0]][0]&'|'&$action[$action[0][0]][1]&'|'&$statusText[0], $lvActions)
		Case $btnDel
			For $i=1 To $action[0][0]
				If $action[$i][2]=GUICtrlRead($lvActions) Then
					GUICtrlDelete($action[$i][2])
					For $h=$i To $action[0][0]-1
						For $x=0 To $action[0][1]
							$action[$h][$x]=$action[$h+1][$x]
						Next
					Next
					ReDim $action[$action[0][0]][$action[0][1]+1]
					$action[0][0]-=1
					ExitLoop
				EndIf
			Next
	EndSwitch
	For $i=1 To $action[0][0]
		If $action[$i][3] And TimerDiff($action[$i][4])>=$action[$i][1] Then
			ConsoleWrite($action[$i][0]&@CRLF)
			$action[$i][4] = TimerInit()
		EndIf
		If $msg=$action[$i][2] Then
			GUICtrlSetData($btnStart, $btnText[$action[$i][3]])
		EndIf
	Next
WEnd
Das kleine Beispiel zeigt, wie man eine dynamische Anzahl von Aktionen in nur 55 Zeilen Code lösen könnte. Der Code könnte durch das verwenden von Funktionen zwar noch deutlich verkürzt werden, jedoch würde darunter die Effizienz teilweise stark leiden.
lolkop is offline  
Thanks
1 User
Old 08/16/2014, 16:21   #8
 
elite*gold: 0
Join Date: May 2008
Posts: 167
Received Thanks: 41
Hm... Offen gesagt verstehe ich den Sinn des Codes (zumindest im Bezug auf das Ausführen von Aktionen) gerade nicht wirklich.

Dem $action-Array Delayzeiten etc. zu übergeben ist klar,
aber wie soll ich daraus die nächste Aufgabe ermitteln?


Zu meinem (bisherigen) Bot-Code:
Jede Quest (insgesamt ca. 50) hat bisher ihren eigenen Funktionsaufruf,
hier beispielsweise für eine Quest:

Code:
Func _checkQuest()
   Send("l") ; öffne das Questlog
   Sleep(500)

   If _checkImage("nachrichtAlina", "questlog_questtext", 160) = 1 Then
   ; Überprüfung, ob die aktuelle Quest mit dieser übereinstimmt
      _nachrichtAlina() ; Funktionsaufruf zur Quest
      Return 1
   EndIf
EndFunc
Code:
Func _nachrichtAlina()
   Send("l") ; Questlog schließen
   Sleep(500)

   _openMap() ; Die Karte wird geöffnet
   Sleep(500)
   _checkImage("map_alina", "mapNavi", 160, 1) ; Mausklick auf "Alina"
   _waitForImage("check_alina", "npc_alina", 120, 120)
   ; Funktion, die alle 500ms eine ImageSearch-Abfrage durchführt, bis diese wahr ist

   Sleep(500)
   _checkImage("questAnnahme", "ansi_dialog", 160, 1) ; Mausklick auf Dialog
   Sleep(500)
   _checkImage("questendDialog", "alina_questabschluss", 180, 1) ; Mausklick auf Dialog
   _rqAbgabe_popup(20)
   ; Funktion ähnlich wie _waitForImage, 
   ; wartet bis ein Popup erscheint um die Questbelohnung abzuholen
   Return 1
EndFunc
Die Image-Funktionen dürften selbsterklärend sein (funktionieren auf ImageSearch-Basis).
Es gibt weitere _nachricht*-Funktionen die komplett gleich aufgebaut sind, jedoch trifft dies bei weitem nicht auf alle Aufgaben zu.

Angenommen die Funktion _nachrichtAlina wurde erkannt und soll jetzt ausgeführt werden.
Um die Sleep-Befehle zu entfernen, kann ich immer nur einen Teil der Funktion aufrufen, da z.B. nach öffnen der Map 500ms gewartet werden soll.

Hierfür könnte ich eine Zustandsvariable benutzen, die hochzählen soll und durch If-Abfragen nur den aktuell benötigten Teil ausführt - auch wenn es den Code unnötig verlängern würde, aber ok.

Das Hauptproblem sehe ich darin, dass ich unter dem EndSwitch im GUI so lange die Funktion _nachrichtAlina() aufrufen müsste, bis diese angibt, dass die Funktion beendet ist bzw. die Quest erfolgreich abgeschlossen wurde.
Genaugenommen geht es mir nicht darum, dass die Funktion aufgerufen werden muss, sondern wie - würde ich die _checkQuest-Funktion so abändern, dass diese einen Return-Wert mit einer Zuordnung zur jeweiligen Quest zurückgibt, könnte ich dazu eine Abfrage starten, die alle 50 Quests abarbeitet und beim Treffer die jeweilige Funktion startet.

ABER: Beeinflusst das nicht enorm die Performance bzw. den Ressourcenverbrauch?
nofuture is offline  
Old 08/16/2014, 19:06   #9
 
elite*gold: 0
Join Date: Mar 2009
Posts: 7,260
Received Thanks: 33,149
Die Funktion kannst du ganz einfach aufrufen, indem du das $action-Array um ein Element erweiterst, den aufzurufenden Funktionsnamen. Statt dem ConsoleWrite() verwendest du einfach die Call() Funktion. Statt dem Funktionsnamen könntest du dem Array auch eine komplette Anweisung übergeben und mittels Execute() ausführen. Wenn du auf Performance und Ressourcenverbrauch achtest solltest du sowohl eine andere Sprache als auch eine andere Herangehensweise in Betracht ziehen (z. B. Speichermanipulation).
Den Kompromiss zwischen Usability, Performance und Ressourcenverbrauch musst du finden, dein Problem mit der GUI wirst du allerdings nicht beheben können, wenn du weiterhin auf Wait-Funktionen oder Sleeps setzt. Theoretisch könntest du sämtliche nicht GUI basierte Befehle in andere Threads auslagern. Das ist zwar auch mit AutoIt (in gewissem Maße) möglich, mit einer anderen Sprache, die Multithreading auch tatsächlich unterstützt, wärst du allerdings besser bedient. Oder du nimmst einen höheren Ressourcenverbrauch in Kauf und nutzt weiterhin AutoIt.
KDeluxe is offline  
Thanks
1 User
Old 08/16/2014, 21:13   #10
 
elite*gold: 0
Join Date: May 2008
Posts: 167
Received Thanks: 41
Grundlegend ist für mich der Ressourcenverbrauch 2.rangig,
es sollte jedoch im Rahmen bleiben, sodass meine Scripts auch auf älteren Computern laufen und diese nicht gleich überfordern.

Die Call()-Funktion ist genau das, was mir gefehlt hat,
ich dachte nun müsste ich an jeder Stelle, an der ich wegen einer Sleep-Funktion unterbrechen müsste, ersteinmal eine Schleife von den 50 Aufgaben durchlaufen um die aktuelle Funktion wieder aufzurufen.
Ich denke mal, das würde den Verbrauch extrem steigern.

Ich danke euch beiden schonmal, ich denke damit kann ich mein Script ordentlich umbauen

Eine kleine Frage hätte ich zum Abschluss noch:
Mittels HotKeySet ist es möglich überall ein Interrupt zu setzen,
egal wie viele Schleifen etc ineinander geschachtelt sind, mit einem Exit- oder Pause-Hotkey kann ich das Script jederzeit unterbrechen.
Wieso ist es dabei möglich, beim drücken eines GUI-Elements allerdings nicht?
Ist nicht genau dafür eigentlich der OnEventMode gedacht?
nofuture is offline  
Reply


Similar Threads Similar Threads
[S]Funktionsfähigen Jad bot
05/06/2013 - Runescape - 0 Replies
Hat einer einen funktionierenden kostenlosen Jad bot? wenn ja bitte posten oder PM zu mir
[S] Funktionsfähigen Levelbot / Auf Privatservern
05/02/2013 - Metin2 - 2 Replies
Würde bei Erfolgreichem Funktionieren , des Levelbots. 7Elitegoldbezahlen.
Hat jemand funktionsfähigen Aimbot
05/19/2010 - Wolfteam - 8 Replies
Hat jemand funktionsfähigen Aimbot? also auto shooten? BItte brauche es...
Problem wenn Buttons Disable dann Enable sind die buttons zum senden zu verwenden
11/19/2009 - AutoIt - 5 Replies
also hab ja durch hilfe geschafft buttons mit Checkbox Enable und disable zu machn nur mein prob ist jetzt das ich die buttons nicht verwenden kann hab schon einiges ausprobiert aber wenn ich dann bsp button1 drücke passiert einfach nix kann mir wer helfen `? bekommt thx für ;) hier der code: #include <GUIConstantsEx.au3> GUICreate("") $check = GUICtrlCreateCheckbox("Enable/Disable Buttons", 10, 10, 140, 20) $button = GUICtrlCreateButton("Button",10,50) $button1 =...
[Buttons]Hi wer kann mir die Buttons erklären
08/16/2009 - Metin2 Private Server - 6 Replies
Hi ich will kg machen,kenne aber die bedeutung der buttons nich könnt ihr mir vllt.helfen MfG TheRisk Hier ein Screen:http://img16.imageshack.us/img16/3016/gaul. jpg



All times are GMT +1. The time now is 11:51.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.