Oppure

Loading
23/05/20 11:54
dylan666
Salve a tutti,
mi trovo a modificare un progetto "ereditato" che a un certo punto nel Form1 ha questo codice (ho tolto il superfluo):

    Shared Function MyCall(myParam1 As UInteger) As Integer
        Dim rtn As Integer
        MsgBox("Test1!", vbSystemModal)
        MsgBox("Test2!!", vbApplicationModal)
        Using form = New Form() With {.TopMost = True}
            MessageBox.Show(form, "Test3!!", "Titolo")
        End Using
        MyCall = rtn
    End Function


Questa funzione viene chiamata "indirettamente" da un bottone con questo codice:
Edit(EditMode.FILE, (AddressOf MyAPI.EditBatch))


EditMode è un Modulo mentre MyAPI è una classe.
EditMode chiama altre funzioni del suo Modulo tra cui una con questo codice:
    Public Function LoadFile() As Integer
        Dim FileInfo As New MYAPIFILEINFO
        FileEditedDelegateFunc = (AddressOf Form1.MyCall)
        LoadFile = result
    End Function


Quindi alla fine del giro viene richiamata MyCall ma le MsgBox che ci sono non sono "bloccanti" per la Form1, cioè posso togliere il focus al messaggio e interagire col Form1 anche se non ho chiuso la finestra. I primi due MsgBox che ho messo generano proprio un'altra icona nella tray-bar di Windows mentre usando il "New Form" si evita questo ma comunque non rende obbligatorio chiudere il messaggio per andare avanti.
Esiste una maniera per ottenere ciò senza modificare il Modulo e la Classe?
Cioè rendere i messaggi bloccanti (tipo vbSystemModal) come se fossero chiamati direttamente dall Form1

Grazie in anticipo
Ultima modifica effettuata da dylan666 24/05/20 21:15
aaa
23/05/20 14:39
dylan666
Ho capito, credo, che il problema sia l'uso di AddressOf, infatti a uno che voleva esattamente l'effetto che io voglio togliere (cioè rendere il MsgBox non bloccante) hanno suggerito questo:


Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
	Dim t As New System.Threading.Thread(AddressOf ShowMSG)
	t.Start()
End Sub

Private Sub ShowMSG()
	MessageBox.Show("hello")
End Sub

social.msdn.microsoft.com/Forums/vstudio/en-US/2bdfdb9c-d54b-4560-a5f6-4372fc98a35f/…

Come posso fare e rendere la MsgBox bloccante in una Sub chiamata con un AddressOf ?
Ultima modifica effettuata da dylan666 23/05/20 20:10
aaa
24/05/20 11:36
Carlo
Ciao dylan666, nel tuo caso specifico, non ho una risposta sicura.
Una MSGbox, lanciata da un nuovo thread, è normale che sia "Modale" o "Dialog" rispetto al suo thread, e non al Form1
La modalità può essere simulata, disattivando il form prima del lancio dell'MSGbox su nuovo thread, e riattivandolo dopo la chiusura dell'MSGbox.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim t As New System.Threading.Thread(AddressOf ShowMSG)
    Me.Enabled = False
    t.Start()
End Sub

Private Sub ShowMSG()
    MessageBox.Show("hello")
    CheckForIllegalCrossThreadCalls = False
    Me.Enabled = True
    Me.TopMost = True
    Me.TopMost = False
End Sub


In allegato un progettino semplice, che illustra la "Modalità" con Show() e ShowDialog(), e sua simulazione.
Ultima modifica effettuata da Carlo 24/05/20 19:48
in programmazione tutto è permesso
24/05/20 15:03
Carlo
l'istruzione CheckForIllegalCrossThreadCalls = False non è il modo più corretto per eseguire l'accesso al controllo 'Form1' da un thread diverso da quello da cui è stata eseguita la creazione.
La procedura corretta è:

Private Delegate Sub SetEnabledCallback(mode As Boolean)

Public Sub SetEnabled(mode As Boolean)
    If Me.InvokeRequired Then
        Dim d As New SetEnabledCallback(AddressOf SetEnabled)
        Me.Invoke(d, New Object() {mode})
    Else
        Me.Enabled = mode
        Me.TopMost = True
        Me.TopMost = False
    End If
End Sub

Public Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim t = New System.Threading.Thread(AddressOf ShowMSG)
    t.Start()
    Me.Enabled = False
End Sub

Public Sub ShowMSG()
    MessageBox.Show("hello")
    Me.SetEnabled(True)
End Sub
Ultima modifica effettuata da Carlo 24/05/20 15:26
in programmazione tutto è permesso
24/05/20 21:13
dylan666
Prima di tutto grazie!
La soluzione è una mescolanza delle due risposte.
Ero arrivato alla prima soluzione di Carlo semplificando e ripulendo il codice trovato qui fino a scriverne uno molto simile al suo:
stackoverflow.com/questions/21512373/…

Continuavo però ad dover dichiarare "Shared" la "Sub ShowMSG" altrimenti il Visual Studio mi segnalava un errore sulla parte "AddressOf" e pur facendo ciò non accettava i "Me.".
Mi sono quindi ricordato che avevo già ceduto al "lato oscuro" di "CheckForIllegalCrossThreadCalls = False" mettendo prima di "Public Class Form1" questo codice:
Public Module MieVar
    Public varForm As Form1
End Module


E al caricamento del "Form1" questo:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        varForm = Me
        CheckForIllegalCrossThreadCalls = False 
    End Sub


Il codice diventa quindi questo:

    Shared Function MyCall(myParam1 As UInteger) As Integer
        Dim rtn As Integer

        varForm.Invoke(New MyDelegate(AddressOf ShowMSG), "Finestra bloccante!")

        MyCall= rtn
    End Function

    Delegate Sub MyDelegate(ByVal msg As String)

    Shared Sub ShowMSG(ByVal msg As String)
        MsgBox(msg)
    End Sub


Lo so, non è assolutamente corretto e dovrei a imparare a usare meglio le "Shared Sub" per evitare l'uso di "CheckForIllegalCrossThreadCalls = False" e assolutamente mi riprometto di farlo!
Grazie per la pazienza e per le due solazioni propostemi!
Ultima modifica effettuata da dylan666 24/05/20 21:18
aaa