none
Comportement de 'keyDown' au niveau de la 'Form'..quand il y a 1 bouton sur cette 'Form' RRS feed

  • Question

  • Bonjour,

    J'ai besoin d'une détection des évènements clavier, au niveau de la 'Form'
    J'avais cru lire qu'il fallait ajouter:

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

    ..pour que la forme prenne le focus en quelque sorte. Or, dès qu'il y a un bouton sur la Form, la détection des touches clavier ne marche plus (par contre, elle marche toujours, si j'utilise KeyUP au lieu de KeyDOWN)

    Pourriez vous me dire quel en est la raison et comment y remédier? Merci

    Public Class Form1
      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.KeyPreview = True 'If you are wanting keypresses at the form level, you need to set the KeyPreview property of the form to True.
      End Sub
      Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
        Select Case e.KeyCode
          Case Keys.Right
            Debug.Print("Right")
          Case Keys.Left
            Debug.Print("Left")
          Case Keys.Up
            Debug.Print("Up")
          Case Keys.Down
            Debug.Print("Down")
        End Select
      End Sub
    End Class
    

     

    mercredi 30 mars 2011 11:37

Réponses

  • Essaie en surchargeant la fontion ProcessCmdKey (qui retourne True si la touche a été traitée)

      Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
          Case Keys.Right
            Debug.Print("Right")
            Return True
          Case Keys.Left
            Debug.Print("Left")
            Return True
          Case Keys.Up
            Debug.Print("Up")
            Return True
          Case Keys.Down
            Debug.Print("Down")
            Return True
          Case Else
            Return MyBase.ProcessCmdKey(msg, keyData)
        End Select
    
      End Function
    
    

     

    mercredi 30 mars 2011 12:41

Toutes les réponses

  • Essaie en surchargeant la fontion ProcessCmdKey (qui retourne True si la touche a été traitée)

      Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
          Case Keys.Right
            Debug.Print("Right")
            Return True
          Case Keys.Left
            Debug.Print("Left")
            Return True
          Case Keys.Up
            Debug.Print("Up")
            Return True
          Case Keys.Down
            Debug.Print("Down")
            Return True
          Case Else
            Return MyBase.ProcessCmdKey(msg, keyData)
        End Select
    
      End Function
    
    

     

    mercredi 30 mars 2011 12:41
  • Foleide._

    Merci pour ta réponse...en effet cela marche!
    Aurais tu quelques secondes pour m'expliquer la mécanique derrière cela?

    - Qu'est ce que une "Protected Overrides Function"?
    - Qu'est ce que le ProcessCmdKey
    - Quelle est l'action de ce "Return My Base.ProcessCmdKey(msg,keydata)?

    Merci pour ton aide!

    mercredi 30 mars 2011 16:39
  • Bonsoir,

    Tout d'avoir, je reviens sur le pourquoi du non fonctionnement. Il semblerait que l'on ne puisse empêcher un bouton de prendre le focus. J'avais vu un article dans lequel un programmeur proposait de dériver le bouton pour pouvoir mettre sa propriété IsDefault à False, même si c'est le seul sur la Form. Je préfère la solution du ProcessCmdKey.

    Protected Overrides : Quand tu crées une Form, tu crées en fait une nouvelle classe qui dérive de Form. De ce fait, tu peux lui ajouter des propriétés, méthodes, évènements. Mais tu peux aussi "transformer" certaines de ses propriétés, méthodes. C'est ce que l'on fait avec "Overrides". Cela permet d'ajouter un traitement, quitte à rendre la main au code d'origine en appelant MyBase.NomPropOuMethode. Dans le cas, présent, cela constitue un "hook" sur le traitement des touches que l'on intercepte à la source. Le mot clé Protected signifie que la méthode ou la propriété est visible pour les classes dérivées. C'est moins que "Public" et plus que "Private" ! Il y a aussi "Friend" qui peut, en supplément, réduire la portée à l'assembly (dll).

    ProcessCmdKey, c'est la procédure qui est appelée par le système pour remettre les touches frappées à la Form. Dans le même genre, et encore plus en amont, on trouve WndProc dans laquelle on peut gérer tous les messages Windows natifs (WM_PAINT, ...). Très partique pour faire du "subclassing", par exemple une fenêtre avec une barre de titre personnalisée, ou sans bordures du tout et que l'on veut déplacer en cliquant n'importe où.

    Comme mentionné ci-dessus, le MyBase.ProcessCmdKey sert à rendre la main pour le reste du traitement. Le Return est à l'attention d'éventuelles classes dérivées.

    Plus d'infos : http://msdn.microsoft.com/fr-fr/library/system.windows.forms.form.processcmdkey(v=vs.90).aspx

    Fred

    mercredi 30 mars 2011 19:07
  • Waow, merci beaucoup Foleide._ pour cette explication très clair et très complete.
    Merci d'avoir pris de ton temps pour m'éclairer!!

    Une dernière chose à laquelle je pense...pourquoi le problème ne se pose t-il pas avec Form1_KeyUp ?

    Et, est-ce que le:

    Me.KeyPreview = True

    ne sert-il pas justement à assurer le focus sur la form

    (c'est juste pour bien comprendre lol)

    Encore merci!!

     


    • Modifié jmdeb mercredi 30 mars 2011 19:29
    mercredi 30 mars 2011 19:19
  • Je ne sais pas !

    Sans doute le bouton est-il moins intéressé par cet évènement :-)

    Néanmoins, je pense qu'il y a un petit bug quelques part, dans la doc ou dans le code, car les deux sont contradictoires (lorsqu'il s'agit du bouton)

    mercredi 30 mars 2011 19:24