Hi,
seit einiger Zeit hänge ich an folgendem Problem:
AutoIt-Script mit GUI ruft per MemoryFuncCall() ein eingebettetes Assemblerprogramm auf. Aus diesem Assemblerprogramm springe ich per Callback in eine AutoIt-Funktion _CB() und nach Abarbeitung einiger Berechnungen wieder zurück ins Assemblerprogramm. Das funktioniert einwandfrei.
Nun folgendes Problem:
Versuche ich, innerhalb der callback-Funktion _CB() das Programm "anzuhalten" (while 1 / wend), bekommt das Hauptfenster nach einigen Sekunden die Meldung "Keine Rückmeldung" . Das kann ich mit ersetzen der while/wend durch eine MsgBox() vermeiden. Das kommt wohl daher, dass die MsgBox() ein echtes modales Fenster ist, mit dementsprechendem Message-Handling.
In der GUI enthaltene Buttons kann ich natürlich per GuiRegisterMsg() auch während der Anzeige der Msgbox abfragen.
Frage:
Was muss ich machen um innerhalb der callback-Funktion ein Warteschleife (ohne Messagebox) zu realisieren ohne dass die GUI die "Keine Rückmeldung"-Message erhält?
Am liebsten wäre mir in der GUI ein "Weiter"-Button, der das angehaltene Script weiterlaufen lässt.
/EDIT/ habe mich schon mit subclasses beschäftigt, ohne da wirklich weiterzukommen. Ich vermute, dass durch die AutoIt/Assembler/callback-AutoIt-Kombination die Messages durcheinanderkommen, obwohl sie sich eigentlich im gleichen Thread(Adressraum) befinden.
Spoiler anzeigen
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
;#include <assembleit.au3>
#include <WindowsConstants.au3>
;32 Bit only
$hgui = GUICreate("test", 400, 200, 20, 20) ;gui erstellen mit button
$hbutton = GUICtrlCreateButton("Button", 20, 20, 100, 40)
GUISetState()
GUIRegisterMsg($WM_COMMAND, "MyWM_COMMAND") ;buttonklicks abfangen
[/autoit] [autoit][/autoit] [autoit]Global $CB = DllCallbackRegister("_CB", "dword", "dword") ;autoitfunktion, die aus assembler angesprungen wird
[/autoit] [autoit][/autoit] [autoit];~ $_assembleit_flag=0
;~ $a = _assembleit("int", "_asm", "int", 5,"ptr",DllCallbackGetPtr($CB)) ;schleife 5x durchlaufen
;~ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $a = ' & $a & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
Global $tCodeBuffer = DllStructCreate("byte[16]") ;reserve Memory for opcodes
DllStructSetData($tCodeBuffer, 1,"0x8B4C240460518B74242CFFD661E2F5C3") ;write opcodes into memory
;assemblerprogramm aufrufen, 5 schleifendurchgänge und adresse callback übergeben
$ret = DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "int", 5, "ptr", DllCallbackGetPtr($CB), "int", 0, "int", 0)
MsgBox(0, "Test", "Fertig")
DllCallbackFree($CB)
Exit
Func _CB($ecx) ;parameter wird aus dem assemblerteil übergeben
ConsoleWrite($ecx & @CRLF) ;parameter, der aus dem assemblerscript übergeben wurde
;folgende 2 zeilen aktivieren, um die "keine Rückmeldung"-Nachricht zu empfangen
;~ while 1
;~ wend
;diese MessageBox soll ersetzt werden durch eine Endlosschleife oder durch ein Fenster bzw Button innerhalb der GUI
MsgBox(0, "_CB() das " & 6 - $ecx & "te mal aufgerufen", "Bitte OK klicken für weiter")
Return 1
EndFunc ;==>_CB
Func MyWM_COMMAND($hwnd, $message, $wParam, $lParam)
Local $sMessage
If _WinAPI_LoWord($wParam) = $hbutton Then ;button gedrückt
MsgBox(0, "MyWM_command", "Button wurde gedrückt", 1)
EndIf
Return $GUI_RUNDEFMSG
EndFunc ;==>MyWM_COMMAND
;~ Func _asm()
;~ _("use32")
;~ _("mov ecx,dword[esp+4]") ;parameter holen = 5
;~ _("@@:") ;label
;~ _("pushad") ;alle register sichern
;~ _("push ecx") ;parameter an autoit übergeben
;~ _("mov esi,dword[esp+44]") ;autoit-funktion callen
;~ _("call esi") ;call
;~ _("popad") ;alle register wieder herstellen
;~ _("loop @b") ;ecx mal (5x) durch die schleife
;~ _("ret")
;~ EndFunc ;==>_asm