
dylan666 (Normal User)
Pro
    
Messaggi: 128
Iscritto: 08/09/2009
|
Salve a tutti,
mi trovo a modificare un progetto "ereditato" che a un certo punto nel Form1 ha questo codice (ho tolto il superfluo):
Codice sorgente - presumibilmente VB.NET |
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:
Codice sorgente - presumibilmente Plain Text |
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:
Codice sorgente - presumibilmente VB.NET |
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 il 24/05/2020 alle 23:15 |
|

dylan666 (Normal User)
Pro
    
Messaggi: 128
Iscritto: 08/09/2009
|
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:
Codice sorgente - presumibilmente VB.NET |
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
|
Ultima modifica effettuata da dylan666 il 23/05/2020 alle 22:10 |
|

Carlo (Member)
Guru
    
Messaggi: 1168
Iscritto: 29/01/2018
|
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.
Codice sorgente - presumibilmente VB.NET |
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 il 24/05/2020 alle 21:48
in programmazione tutto è permesso |
|

Carlo (Member)
Guru
    
Messaggi: 1168
Iscritto: 29/01/2018
|
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 è:
Codice sorgente - presumibilmente VB.NET |
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 il 24/05/2020 alle 17:26
in programmazione tutto è permesso |
|

dylan666 (Normal User)
Pro
    
Messaggi: 128
Iscritto: 08/09/2009
|
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:
https://stackoverflow.com/questions/21512373/how-to-invoke- ...
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:
Codice sorgente - presumibilmente VB.NET |
Public Module MieVar Public varForm As Form1 End Module
|
E al caricamento del "Form1" questo:
Codice sorgente - presumibilmente VB.NET |
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:
Codice sorgente - presumibilmente VB.NET |
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 il 24/05/2020 alle 23:18 |
|