2010-01-06 6 views
3

Je rencontre un problème très particulier. J'ai remarqué que de temps en temps en tapant dans mon TextBox, je vais perdre quelques touches. J'ai ajouté un tas d'instructions de trace dans les événements accrochés par cette TextBox, et j'ai découvert que lorsque j'ai perdu des séquences de touches, les événements KeyUp, KeyDown et KeyPress ont tous été déclenchés correctement, mais l'événement TextChanged n'a jamais été déclenché..NET: événement TextChanged pour TextBox ne se déclenche pas toujours, même si KeyUp et KeyDown tirent

Quelqu'un a-t-il une idée de ce qui se passerait? Je pourrais écrire cela comme un "bug .NET", mais je préférerais savoir s'il y a une solution ici.

Dans le cas où il est suggéré que j'utilise les événements KeyUp/KeyDown pour déterminer si le texte a changé, il y a également un problème. KeyUp/KeyDown sont appelés plusieurs fois pour chaque pression de touche, il serait donc très difficile de déterminer si quelqu'un tapait la même lettre plusieurs fois.

+0

Quelles frappes utilisez-vous pour faire l'expérience de cela? Textchanged fait partie de la propriété Text for the textbox, et toute entrée (alpha et numérique avec des symboles tels que $) déclenche l'événement TextChanged, les touches fléchées, insert, overwrite ne se déclenchent pas mais sont interceptées par l'événement KeyUp/KeyDown . – t0mm13b

+0

Un exemple évident serait d'appuyer sur Retour arrière lorsque la zone de texte est vide. Aucun événement TextChange mais tous les événements de clavier. –

+0

Je suis définitivement en train d'utiliser des frappes alphanumériques normales lorsque cela se produit. – dreadpirateryan

Répondre

1

Je ne sais pas réellement, mais j'ai une supposition aléatoire: Vous exécutez dans une VM?

Un piratage que vous pourriez utiliser est de faire une minuterie qui lit le texte et compare à la valeur précédemment entrée. Appelez le code du gestionnaire d'événements lorsqu'il n'est pas égal à la valeur précédemment vérifiée. Lorsque vous devez utiliser la valeur finale saisie, effectuez une vérification supplémentaire, au cas où la minuterie n'a pas encore été déclenchée.

+0

Non, ne fonctionne pas dans une machine virtuelle. Je vais penser à cette idée de minuterie - bonne suggestion. – dreadpirateryan

0

Voulez-vous dire que la touche est réellement perdue et n'apparaît jamais dans la boîte? Ou voulez-vous dire que vous n'obtenez pas un événement TextChanged pour chaque pression de touche?

Je crois que l'événement TextChanged est piloté par la notification EN_CHANGE du système d'exploitation qui est envoyée via un message WM_COMMAND. Je sais que certains types de messages dans Windows sont «coalisés» pour éviter les notifications redondantes. Par exemple, cela peut arriver avec les messages WM_MOUSEMOVE et c'est pourquoi vous ne recevez pas d'événement de déplacement de la souris pour chaque pixel que la souris déplace sur l'écran.

Je ne peux pas dire avec certitude, mais je soupçonne que l'événement TextChanged se comporte de cette manière aussi. Je peux dire cependant que d'autres méthodes d'entrée ont aussi cet effet secondaire. Lorsque vous utilisez un panneau de saisie Tablet PC, la zone de texte ne reçoit pas de notification TextChanged pour chaque caractère.

+0

La clé est réellement perdue et n'apparaît jamais dans la boîte - et quand cela arrive, j'ai remarqué que l'événement TextChanged ne se déclenche pas aussi bien. Merci pour l'information sur les messages Windows. Peut-être que je peux déclencher manuellement cet événement pendant les événements KeyUp/KeyDown? – dreadpirateryan

+1

Il semble que quelque chose mange le message. Peut-être y a-t-il un hook de message à l'échelle du système installé quelque part qui agit? Ou oserais-je dire, peut-être une sorte de keylogger? Vous devriez essayer Spy ++ si vous l'avez installé et voir si le message arrive à la fenêtre. – Josh

+0

Il y a en effet un crochet de clavier dans le programme - une information importante que j'aurais dû inclure. Le hook est créé à l'aide du code suivant: SetWindowsHookEx (WH_KEYBOARD, KeyFunction, dllInstance, AppDomain.GetCurrentThreadId()); La méthode KeyFunction vérifie certaines frappes de touches, appelle d'autres fonctions en fonction de celles-ci, puis appelle la fonction CallNextHookEx. Mes instructions de trace me disent que dans les cas où je perds des frappes, le crochet voit bien la clé, et la fonction CallNextHookEx est appelée correctement. – dreadpirateryan

2

Hmmm ....

Cela va être un coup de feu, mais, vous avez dit que vous avez le KeyUp, KeyDown et gestionnaires d'événements KeyPress droit? Avez-vous mis le drapeau e.Handled à true dans les gestionnaires d'événements, consultez ici:

 
     private void textBox1_KeyDown(object sender, KeyEventArgs e) 
     { 
      e.Handled = true; 
     } 

     private void textBox1_KeyUp(object sender, KeyEventArgs e) 
     { 
      e.Handled = true; 
     } 

     private void textBox1_KeyPress(object sender, KeyPressEventArgs e) 
     { 
      e.Handled = true; 
     } 

Jetez un coup d'oeil ici dans le MSDN au sujet de cette propriété Handled. (Si vous avez MSDN 2008 SP 1 installé localement, le lien est ms-help://MS.MSDNQTR.v90.en/fxref_system.windows.forms/html/dfc80b44-1d79-6315-cbea-1388a048c018.htm)

Pour citer:

 
Handled is implemented differently by different controls within Windows Forms. 
For controls like TextBox which subclass native Win32 controls, it is 
interpreted to mean that the key message should not be passed to the underlying 
native control. 

If you set Handled to true on a TextBox, that control will not pass the key 
press events to the underlying Win32 text box control, but it will still 
display the characters that the user typed. 

Peut-être qu'il est pas défini dire e.Handled = false; empêchant ainsi l'événement TextChanged de tir?

Pouvez-vous vérifier et confirmer cela?

Edit: Après la réponse de dreadprivateryan, je peux soupçonner (en raison du manque d'un code affiché), en fonction de sa réponse, e.Handled est vrai lorsque la touche Entrée est pressée et fausse pour tout le reste qui dans mon esprit, pense que c'est la raison pour laquelle aucune frappe supplémentaire n'est acceptée à cause de cela.Essayez-vous de mettre le focus sur un autre contrôle lorsque la touche Entrée est enfoncée? Il se peut que KeyUp et KeyDown soient tous les deux en conflit ...

  • Enlever le crochet du clavier et le désactiver ...
  • Ma suggestion est de changer complètement le code de cette manière comme indiqué, sortez KeyDown ou KeyUp Event Handler comme ils sont, de manière simpliste, sont les mêmes, ok, techniquement, il est désigné respectivement pour quand une touche est enfoncée, et de même quand une clé est relâchée. Jetez un oeil à ce lien here. Il y avait une question similaire posté here sur SO. Dans l'exemple ci-dessous, j'ai utilisé le gestionnaire d'événements keyUp pour basculer le focus sur le contrôle disponible suivant lorsque la touche Entrée est enfoncée. Dans le gestionnaire d'événements KeyPress, ceci filtre simplement l'entrée et n'autorise les numéros que de 0 à 9, n'importe quoi d'autre est annulé. Inclus dans ce gestionnaire d'événements, est la possibilité de la touche de retour arrière pour fournir l'édition.

     
         private void textBox1_KeyUp(object sender, KeyEventArgs e) 
         { 
          if (e.KeyCode == Keys.Enter) SendKeys.Send("{TAB}"); 
         } 
         private const string VALID_KEYS = ""; 
         private void textBox1_KeyPress(object sender, KeyPressEventArgs e) 
         {     
          if (VALID_KEYS.IndexOf(char.ToUpper(e.KeyChar)) != -1 || e.KeyChar == (char)8) 
           e.Handled = false;                
          else                     
           e.Handled = true;                 
    }                       
    
    

    Hope this helps, Meilleures salutations, Tom.

  • +0

    Merci pour la suggestion. Je ne mets que e.Handled = true dans le cas où la frappe est une touche d'entrée, et sinon je ne suis pas réglé du tout. Malheureusement, je ne pense pas que cela soit lié à mon problème - je perds des frappes si j'appuie ou non sur Entrée. – dreadpirateryan

    Questions connexes