Clic sur bouton inactif

Résolu
FranckM57 - 7 déc. 2012 à 23:09
 Utilisateur anonyme - 9 déc. 2012 à 22:33
Bonjour,

C'est mon premier post sur ce forum. Voici mon problème.

Lorsque je fais un clic sur un bouton, je veux que cette instruction s'effectue :
- rendre inactif ce bouton + 3 autres ;
- envoyer une information sur le port série ;
- attendre la réponse du port série (ca peut durer plusieurs secondes) ;
- rendre actif les boutons seulement après réception de la réponse.

Avec le code ci dessous, ca fonctionne ... presque.

Lorsque les boutons sont inactifs, si je fais un clic sur l'un d'entre eux rien ne se passe (et c'est tant mieux car c'est ce que je recherche). Mais dès que le bouton devient à nouveau actif, le clic a été mémorisé et l'instruction correspondant à ce bouton est effectuée. Et ca, je ne veux pas.

Comment faire pour que mes boutons inactifs ne mémorisent pas de clic ?
Merci de votre aide.

Franck

'Déplacement Moteur IN
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
InOut = TextBox9.Text
If InOut <> 0 Then
SerialPort8.Write("F-" & InOut)
Button5.Enabled = False
Button6.Enabled = False
Button3.Enabled = False
Button7.Enabled = False
While MouvStop = ""
MouvStop = SerialPort8.ReadLine()
End While
MouvStop = ""
Button5.Enabled = True
Button6.Enabled = True
Button7.Enabled = True
Button3.Enabled = True
TextBox8.Text = PosM - InOut
PosM = TextBox8.Text
End If
End Sub

8 réponses

Utilisateur anonyme
8 déc. 2012 à 14:46
Voici un exemple que tu peux utiliser pour réception et la lecture des données d'un serialport :
Public Class Form1

    Public Delegate Sub DelegateAffichage(ByVal port As IO.Ports.SerialPort)

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        'réception des données
        'on récupère le serialport
        Dim sp As System.IO.Ports.SerialPort = DirectCast(sender, System.IO.Ports.SerialPort)
        'on démarre un thread se référant à MaSub
        Dim t As New Threading.Thread(AddressOf MaSub)
        'on démarre le thread en passant le port en paramètre
        t.Start(sp)
    End Sub

    Private Sub MaSub(ByVal MonPort As System.IO.Ports.SerialPort)
        If Me.InvokeRequired = True Then
            'invocation du délégué avec le port en paramètre
            Me.Invoke(New DelegateAffichage(AddressOf MaSub), MonPort)
        Else
            'lecture des données
            Dim trame(MonPort.BytesToRead - 1) As Byte
            MonPort.Read(trame, 0, trame.Length)
            Dim donnees As String = System.Text.Encoding.ASCII.GetString(trame)
            'traitement et affichage a faire ici
            '....
        End If
    End Sub
End Class
3
Utilisateur anonyme
7 déc. 2012 à 23:50
Bonsoir,

Tu as du remarquer également que ton application était également 'gelée' pendant l'exécution de cette procédure.

On ne doit pas s'y prendre de cette façon mais utiliser l'événement DataReceived du SerialPort

Le code de ton bouton sera ainsi simplifié et c'est seulement à la réception des données récupérées dans la gestion de l'événement que tu réactiveras tes boutons.

Active en même temps, dans les propriétés de ton projet, Option Strict et Option Explicit pour éviter des erreurs de codage comme celle-ci :
InOut = TextBox9.Text
If InOut <> 0 Then 
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
8 déc. 2012 à 00:09
Bonjour,
Je me rappelle avoir eu ce même problème avec VB6 (qui, comme VB.Net, garde en mémoire l'emplacement du click et l'exécute ensuite, même si le bouton est inhibé !)
Je l'avais résolu de manière assez radicale et brutale : inhibition du clavier et de la souris avant le traitement (avant ton While) et re-autorisation en fin de traitement (après ton end while)
Pour bloquer souris et clavier : Fonction BlockInput de la librairie User32 de l'Api de Windows, à moins que VB.Net ne t'offre du plus simple encore.
________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
0
Utilisateur anonyme
8 déc. 2012 à 07:43
Bonjour ucfoutu et bon week end,

En fait, il y a désactivation et réactivation du bouton dans la même procédure. C'est donc logique que le message windows du clic soit exécuté la fois suivante.

En se contentant de désactiver ce bouton tout en envoyant la commande d'écriture sur le SerialPort dans la procédure, on empêche non seulement un clic supplémentaire mais aussi cette boucle while.

A la lecture des données, donc dans une procédure indépendante, on se contentera de traiter les données et de réactiver les boutons.

Pour éviter les opérations inter-threads, nous aurons juste besoin d'implémenter un délégué dans le code comme montré dans le lien que j'ai mentionné plus haut et d'utiliser la méthode Invoke.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
8 déc. 2012 à 08:47
Bonjour, banana32,
Pas si "normal" que cela.
D'ailleurs, je viens de me rappeler une autre parade. Regarde (en VB6) :
Private Sub Command1_Click()

  MsgBox "cliqué"
  Command1.Enabled = False '===>> constate que Command1 est inhibé
  t = Timer
  Do While Timer - t < 5
    DoEvents '===>>> ce doevents change tout, bien que nous soyons dans la même procédure
  Loop
  Command1.Enabled = True

End Sub


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
0
Bonjour,

Merci de votre aide.

J'ai compris cette histoire de mémorisation du clic. L'appli est gelée à cause de while, elle n'exécutera les ordres qu'une fois dégelée mais dégèle qui réactive en même temps les boutons.

L'inhibition de la souris est un peu trop hard pour moi, je vais me diriger vers DataReceived.

Option Strict m'a découvert 35 erreurs facilement corrigées.

C'est mon premier programme. Je reviendrai certainement vous voir.

Franck
0
Bonjour,

banana32, ta proposition fonctionne.
Après Dim donnees As String = System.Text.Encoding.ASCII.GetString(trame), j'ai réactivé mes boutons.
Par contre, je n'arrive pas à afficher les données recues dans une textbox. J'ai fait des recherches, j'ai cru comprendre que cela venait des delegate ou du thread. Mais je n'arrive à rien.

Si vous pouvez encore m'aider .

Franck
0
Utilisateur anonyme
9 déc. 2012 à 22:33
Je t'ai indiqué dans le code ci-dessus l'endroit où faire ton traitement en toute sécurité (à afficher de préférence dans un textbox dont la propriété multiligne est vraie/true) :
Dim donnees As String = System.Text.Encoding.ASCII.GetString(trame)
'traitement et affichage à faire ici
MaTextBoxMultilignes.Text &= donnees
0
Rejoignez-nous