Au fil des flows

9jan/1215

Donner le focus a un controle PictureBox

Posted by Fabien Arcellier

Je developpai un controle de type PictureBox permettant de sélectionner une zone sur une image. Ce controle doit être utilisable directement dans le designer de visual studio. Il ne doit pas necessiter d'implémenter du code en plus dans la form qui l'héberge pour fonctionner.

Parmi les exigences que je m'etais fixé, il y'avait celle ci :

  • Si l'utilisateur appuie sur Escape, le programme annule la sélection en cours

Au moment de réaliser ce scénario, j'ai eu une petite surprise. Le controle PictureBox dont j'hérite n'est pas un controle focusable. Consequence facheuse, un controle qui ne prend pas le focus ne peut intercepter d'evenement clavier, même quand la propriete KeyPreview de l'objet Form parent est active.

Avec Winform, soit dit en passant, ce n'est pas le seul controle à etre ainsi. Voici une liste tiré de la MSDN sur les controles qui ne peuvent prendre le focus :

  • Panel
  • GroupBox
  • ProgressBar
  • Splitter
  • Label
  • LinkLabel (sans link actif)

Premier réflexe, faire une recherche sur Google à ce sujet (avec les mots PictureBox Winform Focus). J'ai trouvé 2 approches :

  • utiliser un bouton flat à la place d'une PictureBox
  • intercepter les evenements claviers sur la Form et les dispatcher

Comme vous vous en doutez, la deuxième solution n'est pas valable pour résoudre le problème fixée. Pour la première, elle est trop abracadabrante pour sembler être la bonne manière.

Rendre un controle Focusable

J'ai donc creusé un peu plus et j'ai trouvé la propriété ControlStyles qui permet de configurer le comportement d'un controle.

Pour lui permettre de pouvoir obtenir le focus, il suffit de lui affecter la propriété Selectable dans son constructeur :

this.SetStyle(ControlStyles.Selectable, true);

Ca ne suffit pas, à présent, il faut donner au controle le moyen de récupérer le focus. Votre controle même si il peut prendre le focus n'a aucun moyen de le faire.

J'ai trouvé la solution (qui est on ne peut plus evidente à la réflexion) sur le forum de StackOverFlow. Il suffit de demander le focus sur l'appel à la méthode OnMouseDown. C'est à dire lors d'un clic de souris sur votre image.

Voici le code qui résume l'approche :

using System;
using System.Drawing;
using System.Windows.Forms;
 
class SelectablePictureBox : PictureBox {
  public SelectablePictureBox() {
    this.SetStyle(ControlStyles.Selectable, true);
  }
  protected override void OnMouseDown(MouseEventArgs e) {
    this.Focus();
    base.OnMouseDown(e);
  }
}
Remplis sous: Non classé 15 Commentaires