Problem mit MsgBox und individuellen Tasten

  • Hallo erst mal an Alle.

    Ich bin ganz neu hier und habe seit einer Woche, nach sehr, sehr langer Zeit, mal wieder ein kleineres Programm mit AutoIt geschrieben.

    In meinem Programm wollte ich auch eine MsgBox mit individuellen Buttons haben.

    Dazu habe ich eine neue MsgBox Funktion erstellt.

    So wie hier von funkey beschrieben:

    MsgBox - Beschreibung der Buttons

    Die MsgBox funktioniert ja (eigentlich), aber sobald die neue MsgBox beendet wird sind die ersten drei Buttons meiner MainGUI auch umbeschriftet.

    Ich habe leider keine Ahnung warum das so ist?

    Wie die Routine von funkey funktioniert versteh ich leider nicht so ganz und deshalb habe ich überhaupt keine Ahnung wo da der Fehler liegt.

    Zum Testen habe ich mal ein kleines Programm erstellt wo man das wunderbar nachvollziehen kann.

    Wäre schön wenn mir mal jemand auf die Sprünge helfen könnte.

    Danke schon mal.


    Testprogramm:

    #include <MsgBoxConstants.au3>

    #include <GUIConstantsEx.au3>

    #include <WinAPI.au3>

    Opt("GUIOnEventMode", 1) ; Change to OnEvent mode

    ; HauptFenster anlegen

    Local $hMainGUI = GUICreate("Test", 200, 160)

    GUISetOnEvent($GUI_EVENT_CLOSE, "CloseButton")

    GUICtrlCreateButton("Button 1", 10, 10, 180)

    GUICtrlSetOnEvent(-1, "Button1")

    GUICtrlCreateButton("Button 2", 10, 40, 180)

    GUICtrlSetOnEvent(-1, "Button2")

    GUICtrlCreateButton("Button 3", 10, 70, 180)

    GUICtrlSetOnEvent(-1, "Button3")

    Local $IDallclose = GUICtrlCreateButton("Close", 10, 130, 180)

    GUICtrlSetOnEvent($IDallclose, "CloseButton")

    GUISetState(@SW_SHOW, $hMainGUI)

    While 1

    Sleep(100)

    WEnd


    Func Button1()

    MsgBoxNew($MB_ABORTRETRYIGNORE,"Titel", "Neue drei Tastenbox mit selbst beschriftbaren Tasten")

    EndFunc

    Func Button2()

    MsgBox($MB_OK, "","Button 2 gedrückt")

    EndFunc

    Func Button3()

    MsgBox($MB_OK, "","Button 3 gedrückt")

    EndFunc

    Func CloseButton()

    Exit

    EndFunc


    ; Tasten von MainGUI werden umbeschriftet???

    ; MsgBox - Beschreibung der Buttons

    ;

    Func MsgBoxNew($flag, $title, $text)

    Local $hProcMsgBox = DllCallbackRegister("CbtHookProcMsgBox", "int", "int;int;int")

    Local $TIDMsgBox = _WinAPI_GetCurrentThreadId()

    Global $hHookMsgBox = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hProcMsgBox), 0, $TIDMsgBox)

    Local $iRet = MsgBox($MB_ABORTRETRYIGNORE, $title, $text, 0)

    _WinAPI_UnhookWindowsHookEx($hHookMsgBox)

    DllCallbackFree($hProcMsgBox)

    Return $iRet

    EndFunc

    Func CbtHookProcMsgBox($nCode, $wParam, $lParam)

    Local $RET = 0, $hBitmap = 0, $xWnd = 0

    If $nCode < 0 Then

    $RET = _WinAPI_CallNextHookEx($hHookMsgBox, $nCode, $wParam, $lParam)

    Return $RET

    EndIf

    Switch $nCode

    Case 5 ;5=HCBT_ACTIVATE

    _WinAPI_SetDlgItemText($wParam, 3, "Ja")

    _WinAPI_SetDlgItemText($wParam, 4, "Nein")

    _WinAPI_SetDlgItemText($wParam, 5, "Vielleicht")

    EndSwitch

    Return

    EndFunc ;==>CbtHookProcMsgBox

    Func _WinAPI_SetDlgItemText($hDlg, $nIDDlgItem, $lpString)

    Local $aRet = DllCall('user32.dll', "int", "SetDlgItemText", "hwnd", $hDlg, "int", $nIDDlgItem, "str", $lpString)

    Return $aRet[0]

    EndFunc ;==>_WinAPI_SetDlgItemText

  • Hi Bernhard,

    die Funktion _WinAPI_SetWIndowsHookEx($WH_CBT, ...) registriert deine Funktion "CbtHookProcMsgBox" als Callback.

    Der Parameter $WH_CBT bedeutet hierbei, dass diese Funktion in folgenden Fällen aufgerufen wird:

    The system calls a WH_CBT hook procedure before activating, creating, destroying, minimizing, maximizing, moving, or sizing a window; [...]

    Der Hook gilt für deine gesamte Anwendung und deshalb wird die Callback-Funktion auch aufgerufen, wenn (nach Schließen der MsgBox) die Main-GUI wieder aktiviert wird.

    Dann überschreibt _WinAPI_SetDlgItemText entsprechend (ungewollt) deine Buttontexte auf der Main-GUI.

    Um dies zu umgehen, fallen mir spontan zwei Workarounds ein:

    1. Die Texte (ja/nein/vielleicht) nur setzen, falls das aktive Fenster nicht die Main-GUI ist:

    Dazu muss einfach nur eine If-Bedingung im Programm eingefügt werden:

    Code
    If $wParam <> $hMainGUI Then
        _WinAPI_SetDlgItemText($wParam, 3, "Ja")
        _WinAPI_SetDlgItemText($wParam, 4, "Nein")
        _WinAPI_SetDlgItemText($wParam, 5, "Vielleicht")
    EndIf

    2. Den Hook nach dem Setzen der Texte in der MsgBox sofort wieder entfernen:

    Dazu muss lediglich die Zeile

    Code
    _WinAPI_UnhookWindowsHookEx($hHookMsgBox)

    an der ursprünglichen Stelle entfernt und stattdessen nach unten verschoben werden:

    Code
    ...
    _WinAPI_SetDlgItemText($wParam, 5, "Vielleicht")
    _WinAPI_UnhookWindowsHookEx($hHookMsgBox)            ; hier einfügen


    Meiner Ansicht nach dürfte Variante 2 die sauberere sein, aber die konkrete Umsetzung bleibt natürlich jedem selbst überlassen ;)

    Viele Grüße

    Xenon

  • Hallo Bernhard65

    Xenon hat dir mit deinem eigentlichen Anliegen ja schon geholfen.

    Ich wollte nur darauf hinweisen, dass es doch viel einfacher wäre eine eigene GUI für die Abfragen zu schreiben.

    (Ich musste etwas lachen, als ich deine Selbstbeschreibung las und dann "DllCallbackRegister, _WinAPI_SetWindowsHookEx, ... Das passte nicht ganz) :)

    PS: Es gibt dazu auch eine nette UDF: https://www.autoitscript.com/forum/topic/10…rsion-2-aug-18/

    Grüße autoiter

  • Ich hab das ganze mal etwas robuster gegen andere Fenster gemacht, die zum gleichen Zeitpunkt auftauchen... Nur den Titel bekomme ich nicht wieder zurückgesetzt -.-

    Da hab ich grad glaub ich ne Denkblockade...

    Aber schau dir den Code unten gern an. Ich habe die Informationen von der Win_Api: https://docs.microsoft.com/de-de/previous…s644977(v=vs.85) genommen und daraus die Strukturen,... gebastelt. :)

  • Hallo Xenon,

    du bist klasse.

    Variante 2 funktioniert prima.

    Scheint mir auch die sauberere (und einfachere) Lösung zu sein.

    Ein großes DANKE von mir! :klatschen:

    autoiter

    Ich verstehe zwar nicht was du mit

    (Ich musste etwas lachen, als ich deine Selbstbeschreibung las und dann "DllCallbackRegister, _WinAPI_SetWindowsHookEx, ... Das passte nicht ganz) :)

    meinst, aber Danke für den Link mit der UDF. Das schau ich mir auf jeden Fall noch genauer an.

    Ich dachte mir schon das dieses Problem mit der MsgBox bestimmt schon mehrere hatten, aber in diesem Forum hab ich nur auf die Lösung gefunden so wie ich sie oben verwendet habe. Ich dem Link von mir oben gibt es zwar noch eine zweite Lösung von L3viathan, die hat aber auch nicht so richtig funktioniert.

    Eventuell muss ich mich halt auch öfters im englischen AutoIt Forum 'herumtreiben'.

    Danke an euch, ich bin erst mal zufrieden.:)


    Hab zwar noch ein ganz anderes Problem, schau aber erst mal ob ich es selbst lösen kann.

  • Ich hab das ganze mal etwas robuster gegen andere Fenster gemacht, die zum gleichen Zeitpunkt auftauchen...

    Das ist natürlich noch mal besser als die bisherige Version! Allerdings würde ich mich an dieser Stelle dann doch eher autoiter anschließen und dafür plädieren, selbst eine einfache GUI zusammenzubasteln oder eine passende UDF zu nutzen. Neben Hooks & Dll-Calls zusätzlich auch noch mit zufälligen Window-Titeln & co. herumzuhantieren macht das Ganze aus meiner Sicht noch unnötig komplexer als es ohnehin schon ist. Zum anderen wäre eine eigene GUI auch deutlich flexibler. Und die erwähnte UDF von Melba sieht auch vielversprechend aus, dann muss man nicht das Rad neu erfinden:

  • So, ich möchte mich nochmal melden.

    Ich habe mir jetzt den Link von autoiter genau angeschaut und muss sagen

    Wow, die UDF ExtMsgBox hat alles was mein Herz begehrt.

    Hab natürlich die alte Lösung komplett raus geschmissen und durch diese ersetzt.


    Aber warum steht den diese Funktion nicht unter den Benutzerdefinierte Funktionsreferenz?

    https://autoit.de/onlinehilfe/online/html/libfunctions.htm

    Das würde doch Sinn machen, oder?

    So habe ich eigentlich nur durch Hilfe von euch von dieser UDF erfahren.

    Ein extra Danke an autoiter für den Link und natürlich an Melba23 der diese UDF erstellt hat.

    :klatschen:

  • Aber warum steht den diese Funktion nicht unter den Benutzerdefinierte Funktionsreferenz?

    [...]

    So habe ich eigentlich nur durch Hilfe von euch von dieser UDF erfahren.

    Weil sie nicht zum offiziellen Teil der AutoIt-Distribution gehört (nicht meine Entscheidung ;)).

    Es gibt aber das (von water gepflegte) Wiki : Liste der User_Defined_Functions

    Unter GUI Additions findest Du dann auch :

    ExtMsgBox (by Melba23) - A very customisable replacement for MsgBox.

    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."

  • Bernhard65 5. Dezember 2019 um 23:19

    Hat das Label von [ offen ] auf [ gelöst ] geändert.