web-dev-qa-db-fra.com

Passer les événements de la souris au contrôle parent

Environnement: .NET Framework 2.0, VS 2008.

J'essaie de créer une sous-classe de certains contrôles .NET (étiquette, panneau) qui passera par certains événements de souris (MouseDown, MouseMove, MouseUp) à son contrôle parent (ou alternativement à la forme de niveau supérieur). Je peux le faire en créant des gestionnaires pour ces événements dans les instances des contrôles standard, par exemple:

public class TheForm : Form
{
    private Label theLabel;

    private void InitializeComponent()
    {
        theLabel = new Label();
        theLabel.MouseDown += new MouseEventHandler(theLabel_MouseDown);
    }

    private void theLabel_MouseDown(object sender, MouseEventArgs e)
    {
        int xTrans = e.X + this.Location.X;
        int yTrans = e.Y + this.Location.Y;
        MouseEventArgs eTrans = new MouseEventArgs(e.Button, e.Clicks, xTrans, yTrans, e.Delta);
        this.OnMouseDown(eTrans);
    }
}

Je ne peux pas déplacer le gestionnaire d'événements dans une sous-classe du contrôle, car les méthodes qui déclenchent les événements dans le contrôle parent sont protégées et je n'ai pas de qualificateur pour le contrôle parent:

Impossible d'accéder au membre protégé System.Windows.Forms.Control.OnMouseDown(System.Windows.Forms.MouseEventArgs) via un qualificatif de type System.Windows.Forms.Control; Le qualificatif doit être de type TheProject.NoCaptureLabel (Ou dérivé de celui-ci).

Je cherche à remplacer la méthode WndProc du contrôle dans ma sous-classe, mais j'espère que quelqu'un pourra me donner une solution plus propre.

31
GentlemanCoder

Oui. Après beaucoup de recherches, j'ai trouvé l'article "Floating Controls, tooltip-style" , qui utilise WndProc pour changer le message de WM_NCHITTEST à HTTRANSPARENT, rendant le Control transparent aux événements de la souris.

Pour cela, créez un contrôle hérité de Label et ajoutez simplement le code suivant.

protected override void WndProc(ref Message m)
{
    const int WM_NCHITTEST = 0x0084;
    const int HTTRANSPARENT = (-1);

    if (m.Msg == WM_NCHITTEST)
    {
        m.Result = (IntPtr)HTTRANSPARENT;
    }
    else
    {
        base.WndProc(ref m);
    }
}

J'ai testé cela dans Visual Studio 2010 avec .NET Framework 4 Client Profile.

64
akatran

Vous devez écrire une méthode publique/protégée dans votre classe de base qui déclenchera l'événement pour vous. Appelez ensuite cette méthode à partir de la classe dérivée.

OR

C'est ce que tu veux?

public class MyLabel : Label
{
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        //Do derived class stuff here
    }
}
3
Autodidact

Le WS_EX_TRANSPARENT le style de fenêtre étendue fait cela (c'est ce que les info-bulles sur place utilisent). Vous voudrez peut-être envisager d'appliquer ce style plutôt que de coder de nombreux gestionnaires pour le faire pour vous.

Pour ce faire, remplacez la méthode CreateParams:

protected override CreateParams CreateParams
{
  get
  {
    CreateParams cp=base.CreateParams;
    cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
    return cp;
  }
}

Pour en savoir plus:

3
Jeff Yates