Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - VB.Net e focus su MsgBOX chiamata da una DLL
Forum - C# / VB.NET - VB.Net e focus su MsgBOX chiamata da una DLL

Avatar
dylan666 (Normal User)
Pro


Messaggi: 115
Iscritto: 08/09/2009

Segnala al moderatore
Postato alle 13:54
Sabato, 23/05/2020
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

  1. Shared Function MyCall(myParam1 As UInteger) As Integer
  2.         Dim rtn As Integer
  3.         MsgBox("Test1!", vbSystemModal)
  4.         MsgBox("Test2!!", vbApplicationModal)
  5.         Using form = New Form() With {.TopMost = True}
  6.             MessageBox.Show(form, "Test3!!", "Titolo")
  7.         End Using
  8.         MyCall = rtn
  9.     End Function



Questa funzione viene chiamata "indirettamente" da un bottone con questo codice:
Codice sorgente - presumibilmente Plain Text

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

  1. Public Function LoadFile() As Integer
  2.         Dim FileInfo As New MYAPIFILEINFO
  3.         FileEditedDelegateFunc = (AddressOf Form1.MyCall)
  4.         LoadFile = result
  5.     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
PM Quote
Avatar
dylan666 (Normal User)
Pro


Messaggi: 115
Iscritto: 08/09/2009

Segnala al moderatore
Postato alle 16:39
Sabato, 23/05/2020
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

  1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
  2.         Dim t As New System.Threading.Thread(AddressOf ShowMSG)
  3.         t.Start()
  4. End Sub
  5.  
  6. Private Sub ShowMSG()
  7.         MessageBox.Show("hello")
  8. End Sub


https://social.msdn.microsoft.com/Forums/vstudio/en-US/2bdf ...

Come posso fare e rendere la MsgBox bloccante in una Sub chiamata con un AddressOf ?

Ultima modifica effettuata da dylan666 il 23/05/2020 alle 22:10
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 602
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 13:36
Domenica, 24/05/2020
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

  1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
  2.     Dim t As New System.Threading.Thread(AddressOf ShowMSG)
  3.     Me.Enabled = False
  4.     t.Start()
  5. End Sub
  6.  
  7. Private Sub ShowMSG()
  8.     MessageBox.Show("hello")
  9.     CheckForIllegalCrossThreadCalls = False
  10.     Me.Enabled = True
  11.     Me.TopMost = True
  12.     Me.TopMost = False
  13. End Sub



In allegato un progettino semplice, che illustra la "Modalità" con Show() e ShowDialog(), e sua simulazione.


Carlo ha allegato un file: Modal.zip (77809 bytes)
Clicca qui per scaricare il file

Ultima modifica effettuata da Carlo il 24/05/2020 alle 21:48


in programmazione tutto è permesso
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 602
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 17:03
Domenica, 24/05/2020
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

  1. Private Delegate Sub SetEnabledCallback(mode As Boolean)
  2.  
  3. Public Sub SetEnabled(mode As Boolean)
  4.     If Me.InvokeRequired Then
  5.         Dim d As New SetEnabledCallback(AddressOf SetEnabled)
  6.         Me.Invoke(d, New Object() {mode})
  7.     Else
  8.         Me.Enabled = mode
  9.         Me.TopMost = True
  10.         Me.TopMost = False
  11.     End If
  12. End Sub
  13.  
  14. Public Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
  15.     Dim t = New System.Threading.Thread(AddressOf ShowMSG)
  16.     t.Start()
  17.     Me.Enabled = False
  18. End Sub
  19.  
  20. Public Sub ShowMSG()
  21.     MessageBox.Show("hello")
  22.     Me.SetEnabled(True)
  23. End Sub


Ultima modifica effettuata da Carlo il 24/05/2020 alle 17:26


in programmazione tutto è permesso
PM Quote
Avatar
dylan666 (Normal User)
Pro


Messaggi: 115
Iscritto: 08/09/2009

Segnala al moderatore
Postato alle 23:13
Domenica, 24/05/2020
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

  1. Public Module MieVar
  2.     Public varForm As Form1
  3. End Module



E al caricamento del "Form1" questo:

Codice sorgente - presumibilmente VB.NET

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



Il codice diventa quindi questo:

Codice sorgente - presumibilmente VB.NET

  1. Shared Function MyCall(myParam1 As UInteger) As Integer
  2.         Dim rtn As Integer
  3.  
  4.         varForm.Invoke(New MyDelegate(AddressOf ShowMSG), "Finestra bloccante!")
  5.  
  6.         MyCall= rtn
  7.     End Function
  8.  
  9.     Delegate Sub MyDelegate(ByVal msg As String)
  10.  
  11.     Shared Sub ShowMSG(ByVal msg As String)
  12.         MsgBox(msg)
  13.     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
PM Quote