ContextMenuStrip et Focus

Résolu
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010 - 10 nov. 2009 à 10:33
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010 - 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.

10 réponses

TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 13:34
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
3
cboulas Messages postés 2641 Date d'inscription mercredi 2 juin 2004 Statut Membre Dernière intervention 8 janvier 2014 16
10 nov. 2009 à 10:58
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
0
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 11:16
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
0
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 11:26
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

}
0

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

Posez votre question
cboulas Messages postés 2641 Date d'inscription mercredi 2 juin 2004 Statut Membre Dernière intervention 8 janvier 2014 16
10 nov. 2009 à 11:26
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
0
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 11:42
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.
0
cboulas Messages postés 2641 Date d'inscription mercredi 2 juin 2004 Statut Membre Dernière intervention 8 janvier 2014 16
10 nov. 2009 à 12:36
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
0
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 12:56
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.
0
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 13:10
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
0
TotoLePaBo Messages postés 11 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 22 août 2010
10 nov. 2009 à 13:19
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.
0
Rejoignez-nous