ContextMenuStrip et Focus [Résolu]

TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 10:33 - Dernière réponse : TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention
- 10 nov. 2009 à 13:34
Bonjour,

J'ai pour but de réaliser une autocomplétion un peu plus 'sophistiquée' que l'autocomplétion
proposée avec le AutoCompleteStringCollection. (propriété des controles TextBox, ComboBox, ...)
Je dois en effet rechercher des chaines de caracteres 'ressemblantes', incluant donc des possibilités
de fautes de frappe, et je n'ai malheureusement pas pu customiser le comportement de l'autocomplétion
du framework.

J'ai donc commencé a faire du code 'a la mano'. Au bout de la frappe de quelques caractères dans une TextBox,
celle-ci affiche un ContextMenuStrip des éléments ressemblants.

Le problème est qu'une fois le ContextMenuStrip affiché, j'ai beau redonner le focus a ma TextBox, les évènements
claviers sont attrappés uniquement par le ContextMenuStrip, et je ne peux donc plus rentrer de texte dans le champ de
la TextBox

Est-ce que quelqu'un aurait une id?

Merci de vos réponses

David.
Afficher la suite 

Votre réponse

10 réponses

Meilleure réponse
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 13:34
3
Merci
Bon, je m'étais trompé d'évènement:

dans la classe MatchMenuStrip:

#region Properties

private PreviewKeyDownEventArgs _event;
public PreviewKeyDownEventArgs Event {
get { return _event; }
set { _event = value; }
}

#endregion

#region Events

void MatchMenuStrip_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
if (e.KeyCode != Keys.Down && e.KeyCode != Keys.Up) { //on conserve quand meme la possibilité de naviguer par les fleches
this.Event = e;
this.Close();
}
}

void MatchMenuStrip_Closed(object sender, ToolStripDropDownClosedEventArgs e) {
if (this.Event != null) {
PostMessage(this.UserControl.GetTextBoxHandle(), WM_KEYDOWN, this.Event.KeyValue, 0);
}
}

#endregion







Voila plus de 'bug' tout fonctionne comme je voulais.

Eventuellement toujours preneur d'une solution sans DLL user32


David

Merci TotoLePaBo 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 118 internautes ce mois-ci

Commenter la réponse de TotoLePaBo
cboulas 2641 Messages postés mercredi 2 juin 2004Date d'inscription 8 janvier 2014 Dernière intervention - 10 nov. 2009 à 10:58
0
Merci
Hello,

En fait soit tu met une variable Static que tu réutiliser au lost focus, soit lors du lost focus tu altère directement le texte de la textbox

Chris...
- La vérité n'est pas ailleurs, elle est sous le nez de chacun, quelques mouvements neuronale permettent de l'entrevoir -
MCPD (webform-winform) / MCSA / MCDST / MCT
Commenter la réponse de cboulas
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 11:16
0
Merci
Salut,

Merci pour ta réponse, mais je n'ai pas tout compris...
Le probleme est :

- ma TextBox a bien le focus (this.MyTextBox.Focused = true)
- mon ContextMenuStrip est visible mais n'a pas le focus (this.MyContextMenu.Focused = false)
- le curseur 'Beam' apparait bien clignotant dans ma TextBox

Mais la frappe d'une touche au clavier est détectée au niveau du ContextMenuStrip.... (alors qu'il n'a pas le focus )
et donc, ma textbox ne se remplit plus et ne génère aucun évènement (TextChanged, KeyDown,...)

Penses tu encore ta solution acceptable?

David
Commenter la réponse de TotoLePaBo
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 11:26
0
Merci
Pour info, voici une partie du code:


public partial class UCAbstractMatch : UserControl {

#region Properties

private IMatchableCollection _collection;
public IMatchableCollection Collection {
get {
if (_collection == null) {
_collection = this.InitCollection();
}
return _collection;
}
set { _collection = value; }
}

private IMatchable _match;
public IMatchable Match {
get { return _match; }
set { _match = value; }
}

private UCMatchMenu _menu;
public UCMatchMenu Menu {
get { return _menu; }
set { _menu = value; }
}

private ContextMenuStrip _menuStrip;
public ContextMenuStrip MenuStrip {
get { return _menuStrip; }
set { _menuStrip = value; }
}

#endregion

#region Constructor

public UCAbstractMatch() {
InitializeComponent();
}

#endregion

#region Methods

protected virtual IMatchableCollection InitCollection() {
return null;
}

#endregion

#region Events

private void txtMatch_TextChanged(object sender, EventArgs e ) {
if (txtMatch.Text.Length > 3) {
List filtre = this.Collection.Matches(this.txtMatch.Text);
this.MenuStrip = new MatchMenuStrip(filtre, this);
this.MenuStrip.Show(this.txtMatch, new Point(0, this.txtMatch.Height));
this.Focus();
this.txtMatch.Focus();
this.txtMatch.Select(); //repasse le focus a la TextBox donc....
}
}
}


public class MatchMenuStrip : ContextMenuStrip {

#region Properties

private List _collection;
public List Collection {
get { return _collection; }
set { _collection = value; }
}

private UCAbstractMatch _userControl;
public UCAbstractMatch UserControl {
get { return _userControl; }
set { _userControl = value; }
}

#endregion

#region Constructor

public MatchMenuStrip(List collection, UCAbstractMatch control)
: base() {
this.Collection = collection;
this.UserControl = control;
this.InitializeComponent();
this.Opacity = 0.8;
this.TabStop = false;
}


#endregion

#region Methods

private void InitializeComponent() {
this.SuspendLayout();
foreach (IMatchable match in this.Collection) {
ToolStripMenuItem item = new ToolStripMenuItem();
item.Size = new System.Drawing.Size(133, 22);
item.Text = match.Value;
this.Items.Add(item);
}

this.Size = new System.Drawing.Size(134, 126);
this.ResumeLayout(false);
}

#endregion

}
Commenter la réponse de TotoLePaBo
cboulas 2641 Messages postés mercredi 2 juin 2004Date d'inscription 8 janvier 2014 Dernière intervention - 10 nov. 2009 à 11:26
0
Merci
Effectivement j'avais mal pigé, pourquoi ne transfert tu pas ce que le contextmenustrip reçoi en frappe dans la textbox, histoire de contourner le pb ?

Car lorsque tu tape dans le textbox, il ouvre le context... et lui prend automatiquement le focus, donc soit tu redonne le focus à la textbox, soit tu transfert ce que lui reçoi histoire de "simuler" la frappe dans la textbox

Chris...
- La vérité n'est pas ailleurs, elle est sous le nez de chacun, quelques mouvements neuronale permettent de l'entrevoir -
MCPD (webform-winform) / MCSA / MCDST / MCT
Commenter la réponse de cboulas
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 11:42
0
Merci
Il n'y a pas de mal, je m'étais certainement mal expliqué... ;)

<<donc soit tu redonne le focus à la textbox>> --> c'est fait! elle a le focus , le curseur clignotant et tout.
<<soit tu transfert ce que lui reçoi histoire de "simuler" la frappe dans la textbox>> --> j'y ai déja pensé, mais certaines
touches spéciales sont légèrement 'chaudes' a gérer (suppr, backspace, shift, etc....) et sont interprétés comme des touches de navigation
par le ContextMenuStrip (), et donc non relevées par les habituels KeyDown, KeyUp, ... . Cela revient donc pratiquement a développer un hook clavier.... Tout ça pour une TextBox mdr

En fait, je pensais que quelqu'un aurait posté un message du genre : Mais tu es c.. , tout ca c'est normal, tu as oublié de mettre
la propriété X a true/false sur le controle Y ;)

Désolé cboulas, je laisse le post ouvert ;)

David.
Commenter la réponse de TotoLePaBo
cboulas 2641 Messages postés mercredi 2 juin 2004Date d'inscription 8 janvier 2014 Dernière intervention - 10 nov. 2009 à 12:36
0
Merci
lors du KeyDown par exemple tu fait cela

private ..._keydown(sender, e)
{
maTextBox_KeyDown(sender, e);
..._KeyDown.Cancel = true;
}


Chris...
- La vérité n'est pas ailleurs, elle est sous le nez de chacun, quelques mouvements neuronale permettent de l'entrevoir -
MCPD (webform-winform) / MCSA / MCDST / MCT
Commenter la réponse de cboulas
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 12:56
0
Merci
L'evenement sur KeyDown (KeyEventArgs) n'a pas de propriété Cancel...
Il a deux propriétés interessantes : Handled et SupressKeyPress mais quelques soient les valeurs,
rien n'y change....

Je passe a une solution 'code pas clair' : Je ferme le ContextMenuStrip sur l'evenement KeyDown.
(la saisie fonctionne alors a nouveau sur la textbox)
Probleme : la touche qui a fermé le ContextMenuStrip n'est pas retournée a la TextBox.
Je vais essayer de faire fonctionner PostMessage de user32.dll pour simuler l'appui de la touche clavier
a la fermeture du ContextMenuStrip... (en gros c'est crade)

Je tiendrai au courant du résultat...

David.
Commenter la réponse de TotoLePaBo
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 13:10
0
Merci
Ouah! ca marche en partie....

J'ai rajouté ça comme code:

Dans UCAbstractMatch un méthode publique:

public IntPtr GetTextBoxHandle() {
return this.txtMatch.Handle;
}

Dans MatchMenuStrip :

#region DLL System
[DllImport("user32.dll")]
private static extern bool PostMessage(
IntPtr hWnd, // handle to destination window
UInt32 Msg, // message
Int32 wParam, // first message parameter
Int32 lParam // second message parameter
);

const int WM_KEYDOWN = 0x100;

#endregion

#region Properties

private KeyEventArgs _event;

#endregion

#region Events

void MatchMenuStrip_Closed(object sender, ToolStripDropDownClosedEventArgs e) {
if (this._event != null) {
PostMessage(this.UserControl.GetTextBoxHandle(), WM_KEYDOWN, this._event.KeyValue, 0);
}
}

void MatchMenuStrip_KeyDown(object sender, KeyEventArgs e) {
this._event = e;
this.Close();
}

#endregion
Commenter la réponse de TotoLePaBo
TotoLePaBo 11 Messages postés samedi 23 février 2008Date d'inscription 22 août 2010 Dernière intervention - 10 nov. 2009 à 13:19
0
Merci
Tout marche ou presque:

l'appui sur une touche classique et DEL ferme le ContextMenuStrip, et insere dans la TextBox, avec réouverture d'un
nouveau ContextMeuStrip.
Les touches de direction (gauche droite) ferment le ContextMenuStrip mais n'ont aucune action dans la TextBox
Le pire est la touche Backspace ou retour en début ligne qui donnent le focus aux ToolStripMenuItem.


Voila il y a encore du travail ;)

Je suis toujours preneur d'une solution moins 'crade'


David.
Commenter la réponse de TotoLePaBo

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.