B4J Question Programmatically detect that a message box is open

Didier99

Member
Is there a way (aside from creating a flag/semaphore) to detect that a message box (MsgBox2Async) is open and the program is waiting for the user to close it?
 

William Lancee

Well-Known Member
Licensed User
Longtime User
There are several ways, the easiest it this (put in B4XPages template to run):

B4X:
Private Sub Button1_Click
    Dim sf As Object = xui.Msgbox2Async("Delete file?", "Title", "Yes", "Cancel", "No", Null)
    CallSubDelayed2(Me, "IsWaiting", True)
    Wait For (sf) Msgbox_Result (Result As Int)
    CallSubDelayed2(Me, "IsWaiting", False)
    If Result = xui.DialogResponse_Positive Then
        Log("Deleted!!!")
    End If
End Sub

Private Sub IsWaiting(Waiting As Boolean)
    If Waiting Then
        Log("Now waiting")
    Else
        Log("Msg Closed")
    End If
End Sub
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
If you have multiple messages waiting, here is another approach using JavaObject
B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private multipleMsgs As Map 'tracks msgs
End Sub

Public Sub Initialize
    multipleMsgs.Initialize
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    TestWaitingMethod
End Sub

Private Sub TestWaitingMethod
    '....Some code
    ShowMessage1
    '....Some code
    ShowMessage2
 
    'Test if any messages are waiting - test method
    For i = 0 To 10
        testForWaitingMessages
        Sleep(1000)
    Next
End Sub

Private Sub testForWaitingMessages
    For Each kw As String In multipleMsgs.Keys
        Dim msg As Object = multipleMsgs.Get(kw)
        Dim jo As JavaObject = msg
        Dim result As String = jo.RunMethod("isShowing", Null)
        Log(kw & TAB & result)
    Next
    Log(TAB)
    'Log output
    'Delete file?    true
    'Finished task?    true

'  After closing msg2
    'Delete file?    true
    'Finished task?   false

'  After closing msg1
    'Delete file?    false
    'Finished task?    false
End Sub

Private Sub ShowMessage1
    Dim sf As Object = xui.Msgbox2Async("Delete file?", "Title", "Yes", "Cancel", "No", Null)
    multipleMsgs.Put("Delete file?", sf)
    Wait For (sf) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Log("Deleted!!!")
    End If
End Sub

Private Sub ShowMessage2
    Dim sf As Object = xui.Msgbox2Async("Finished task?", "Title", "Yes", "Cancel", "No", Null)
    multipleMsgs.Put("Finished task?", sf)
    Wait For (sf) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Log("Finished!!!")
    End If
End Sub
 

Attachments

  • msgRunning.zip
    7.7 KB · Views: 38
Last edited:
Upvote 0

Didier99

Member
Thank you. This is pretty much what I did but I was wondering if there was a more elegant way to directly poll the status of the MsgBox2ASync widget from another function. Apparently there is not.
 
Upvote 0

Didier99

Member
Yes, this is a more evolved version of the flag/semaphore paradigm. This one will cover multiple use-cases.
Thank you
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
You can achieve the results of #3 without the tracking map by naming the message objects uniquely, and making them global.
Then, you can poll them individually directly.

B4X:
Private Sub TestWaitingMethod
    'In Globals:    Private deleteMsg, finishedMsg As Object
    
    '....Some code
    ShowMessage1
    '....Some code
    ShowMessage2
    Log("deleteMsg waiting " & MsgWaiting(deleteMsg))        '    deleteMsg waiting true
    Log("finishedMsg waiting " & MsgWaiting(finishedMsg))    '    finishedMsg waiting true

'    finishedMsg waiting True

    'Close message 2 when log appears
    Sleep(3000)
    Log("deleteMsg waiting " & MsgWaiting(deleteMsg))        '    deleteMsg waiting true
    Log("finishedMsg waiting " & MsgWaiting(finishedMsg))    '    finishedMsg waiting false

    'Close message 1 when log appears
    Sleep(3000)
    Log("deleteMsg waiting " & MsgWaiting(deleteMsg))        '    deleteMsg waiting false
    Log("finishedMsg waiting " & MsgWaiting(finishedMsg))    '    finishedMsg waiting false

End Sub

Private Sub MsgWaiting(msg As JavaObject) As Boolean
    Return msg.RunMethod("isShowing", Null)
End Sub

Private Sub ShowMessage1
    deleteMsg = xui.Msgbox2Async("Delete file?", "Title", "Yes", "Cancel", "No", Null)
    Wait For (deleteMsg) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Log("Deleted!!!")
    End If
End Sub

Private Sub ShowMessage2
    finishedMsg = xui.Msgbox2Async("Finished task?", "Title", "Yes", "Cancel", "No", Null)
    Wait For (finishedMsg) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Log("Finished!!!")
    End If
End Sub
 
Upvote 0

Didier99

Member
Great, this is exactly what I was looking for, thank you!
 
Upvote 0

MrKim

Well-Known Member
Licensed User
Longtime User
Why not just use Wait For when you call the function that has the message box? Then your other code won't run until the message box is closed.
That is what I do, of course sometimes I have had to add wait for for 3 or 4 levels .
 
Upvote 0

Didier99

Member
Why not just use Wait For when you call the function that has the message box? Then your other code won't run until the message box is closed.
That is what I do, of course sometimes I have had to add wait for for 3 or 4 levels .
"I have had to add wait for for 3 or 4 levels"
This was exactly what I was trying to prevent
Wait For can be a blessing or a curse, or both!
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…