Je continue à programmer une sorte de navigation au clavier dans mon programme graphique simple (en C #). Et j'ai eu des ennuis encore une fois.
Mon problème est que je veux traiter l'entrée au clavier pour déplacer un calque. Déplacer le calque avec la souris fonctionne déjà assez bien, mais le contrôle n’a pas le focus ( ni KeyUp/KeyDown/KeyPress ni GotFocus/LostFocus n’est déclenché pour ce contrôle ). ma classe dérive de Panel (et écrase quelques événements), j'ai également écrasé les événements mentionnés ci-dessus, mais je ne peux pas réussir à les déclencher.
Je pense que je pourrais réussir à mettre en œuvre la réponse au clavier en utilisant quelque chose comme Keyboard.GetState () ou ProcessCmdWnd ou quelque chose. Cependant: je dois encore être capable de dire quand le contrôle a le focus.
Existe-t-il un moyen plus ou moins élégant d’ajouter cette possibilité à un contrôle utilisateur (basé sur Panel)?
J'ai vérifié beaucoup de discussions ici et je pourrais utiliser cette approche pour la saisie au clavier. Le problème de focalisation reste cependant toujours.
Merci beaucoup pour l'information à l'avance!
Igor.
p.s .: Je programme en C # .NET v3.5, avec VS2008. C'est une application Windows.Forms, pas WPF .
La classe Panel a été conçue en tant que conteneur, elle évite de prendre le focus de sorte qu'un contrôle enfant l'obtiendra toujours. Vous aurez besoin d'une intervention chirurgicale pour résoudre ce problème. J'ai ajouté le code pour obtenir des traits de touche de curseur dans l'événement KeyDown également:
using System;
using System.Drawing;
using System.Windows.Forms;
class SelectablePanel : Panel {
public SelectablePanel() {
this.SetStyle(ControlStyles.Selectable, true);
this.TabStop = true;
}
protected override void OnMouseDown(MouseEventArgs e) {
this.Focus();
base.OnMouseDown(e);
}
protected override bool IsInputKey(Keys keyData) {
if (keyData == Keys.Up || keyData == Keys.Down) return true;
if (keyData == Keys.Left || keyData == Keys.Right) return true;
return base.IsInputKey(keyData);
}
protected override void OnEnter(EventArgs e) {
this.Invalidate();
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e) {
this.Invalidate();
base.OnLeave(e);
}
protected override void OnPaint(PaintEventArgs pe) {
base.OnPaint(pe);
if (this.Focused) {
var rc = this.ClientRectangle;
rc.Inflate(-2, -2);
ControlPaint.DrawFocusRectangle(pe.Graphics, rc);
}
}
}
Le même code Hans Passant dans VB.NET
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Public Class SelectablePanel
Inherits Panel
Public Sub SelectablePanel()
Me.SetStyle(ControlStyles.Selectable, True)
Me.TabStop = True
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
Me.Focus()
MyBase.OnMouseDown(e)
End Sub
Protected Overrides Function IsInputKey(ByVal keydata As Keys) As Boolean
If (keydata = Keys.Up OrElse keydata = Keys.Down) Then Return True
If (keydata = Keys.Left OrElse keydata = Keys.Right) Then Return True
Return MyBase.IsInputKey(keydata)
End Function
Protected Overrides Sub OnEnter(ByVal e As EventArgs)
Me.Invalidate()
MyBase.OnEnter(e)
End Sub
Protected Overrides Sub OnLeave(ByVal e As EventArgs)
Me.Invalidate()
MyBase.OnLeave(e)
End Sub
Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
MyBase.OnPaint(pe)
If (Me.Focused) Then
Dim rc As Rectangle = Me.ClientRectangle
rc.Inflate(-2, -2)
ControlPaint.DrawFocusRectangle(pe.Graphics, rc)
End If
End Sub
End Class
L’astuce la plus simple que j’utilise lorsque, pour une raison quelconque, je ne peux pas utiliser la propriété parent KeyPreview de formulaire pour que le formulaire traite les événements de clé, consiste à placer une zone de texte sur
Le panel:
Panel.Controls.Add(_focusTextBox = new TextBox() { Visible = true , Left = -300, TabIndex = 0});
Et utilisez-le pour capturer l'événement KeyDown:
_focusTextBox.KeyDown += panel_KeyDown;
La dernière étape consiste à définir le focus sur cette zone de texte lorsque d'autres contrôles du panneau ont cliqué:
_focusTextBox.Focus();
appelez le focus dans l'événement de clic
private void Panel_Click(object sender, EventArgs e)
{
Panel.Focus();
}
Pour obtenir le focus, recherchez l'événement MouseEnter dans la fenêtre Propriétés.
Écrivez ci-dessous le code:
private void mainPanel_MouseEnter(object sender, EventArgs e)
{
mainPanel.Focus();
}