2008-10-07 14 views
5

Ich habe ein C# -Formular (nennen wir es MainForm) mit einer Reihe von benutzerdefinierten Steuerelementen darauf. Ich möchte, dass die MainForm.OnClick() -Methode immer dann ausgelöst wird, wenn jemand auf das Formular klickt, unabhängig davon, ob der Klick auf dem Formular erfolgt ist oder ob der Klick auf einem der benutzerdefinierten Steuerelemente erfolgt ist. Ich suche nach einem ähnlichen Verhalten wie die KeyPreview-Funktion von Formularen, mit Ausnahme von Mausklicks anstelle von Tastendrücken.Wie lege ich ein Click-Ereignis für ein Formular fest?

Antwort

2

Fügen Sie im ControlAdded-Ereignis des Formulars dem Steuerelement einen MouseClick-Handler mit der Adresse des click-Ereignisses des Formulars hinzu. Ich habe das nicht getestet, aber es könnte funktionieren.

+0

Dies scheint immer noch ein bisschen ein Hack zu sein, aber das scheint die beste Option zu sein, die ich habe. – Mykroft

0

Ein Klick auf einen offenen Bereich im Formular ist einfach, aber um einen Klick zu erhalten, der tatsächlich auf einem Steuerelement ist, benötigen Sie die Zusammenarbeit dieses Steuerelements, um es an das Formular zu senden.

Eine Möglichkeit besteht darin, ein transparentes Steuerelement über das gesamte Formular zu platzieren und Klicks darauf zu akzeptieren, mit ihnen umzugehen und sie dann an das richtige Steuerelement darunter zu übergeben.

+0

Ich habe das Gefühl, dass es eine elegantere Lösung als diese geben muss. – Mykroft

1

Die einzige Möglichkeit, die ich jemals geschafft habe, ist die Behandlung des [c] Click [/ c] -Ereignisses jedes Steuerelements. Ich glaube nicht, dass das Ereignis ausgelöst wird, bevor es von der Steuerung verarbeitet wird.

In WPF gibt es "Tunneling" Vorschau-Ereignisse, die diese Funktionalität bieten, aber das hilft Ihnen nicht wirklich in WinForms.

+0

Nun, es ist zu spät, jetzt zu WPF zu wechseln, aber ich werde ernsthaft darüber nachdenken, es in Zukunft zu verwenden. – Mykroft

1

Sie können alle Ereignisse des Steuerelements haken, wenn Sie möchten, und dann auf diese Weise überwachen. Ich nehme an, es gibt einige übermäßig Win32 api Weg, sie alle zu fangen, aber das ist im Moment über mich.

public Form1() 
    { 
     InitializeComponent(); 
     HookEvents(); 
    } 

    private void HookEvents() { 
     foreach (Control ctl in this.Controls) { 
      ctl.MouseClick += new MouseEventHandler(Form1_MouseClick); 
     } 
    } 

    void Form1_MouseClick(object sender, MouseEventArgs e) 
    { 
     LogEvent(sender, "MouseClick"); 
    } 

    // and then this just logs to a multiline textbox you have somwhere on the form 
    private void LogEvent(object sender, string msg) { 
     this.textBox1.Text = string.Format("{0} {1} ({2}) \n {3}", 
      DateTime.Now.TimeOfDay.ToString(), 
      msg, 
      sender.GetType().Name, 
      textBox1.Text 
      ); 
    } 

Der Ausgang ist so etwas, alle Ereignisse zeigt, und die "gesendet", um sie nach oben:

14:51:42.3381985 MouseClick (Form1) 
14:51:40.6194485 MouseClick (RichTextBox) 
14:51:40.0100735 MouseClick (TextBox) 
14:51:39.6194485 MouseClick (Form1) 
14:51:39.2131985 MouseClick (RichTextBox) 
14:51:38.8694485 MouseClick (Button) 

HTH.

6

Ich empfehle das Erstellen eines Basisformulars für die anderen Formulare in Ihrer Anwendung zu erben. Fügen Sie diesen Code auf Ihre Basis bildet ein neues Ereignis erstellen GlobalMouseClickEventHandler genannt:

namespace Temp 
{ 
    public delegate void GlobalMouseClickEventHander(object sender, MouseEventArgs e); 

    public partial class TestForm : Form 
    { 
     [Category("Action")] 
     [Description("Fires when any control on the form is clicked.")] 
     public event GlobalMouseClickEventHander GlobalMouseClick; 

     public TestForm() 
     { 
      InitializeComponent(); 
      BindControlMouseClicks(this); 
     } 

     private void BindControlMouseClicks(Control con) 
     { 
      con.MouseClick += delegate(object sender, MouseEventArgs e) 
      { 
       TriggerMouseClicked(sender, e); 
      }; 
      // bind to controls already added 
      foreach (Control i in con.Controls) 
      { 
       BindControlMouseClicks(i); 
      } 
      // bind to controls added in the future 
      con.ControlAdded += delegate(object sender, ControlEventArgs e) 
      { 
       BindControlMouseClicks(e.Control); 
      };    
     } 

     private void TriggerMouseClicked(object sender, MouseEventArgs e) 
     { 
      if (GlobalMouseClick != null) 
      { 
       GlobalMouseClick(sender, e); 
      } 
     } 
    } 
} 

Diese Lösung funktioniert nicht nur für die Top-Level-Kontrollen, aber auch Kontrollen verschachtelt wie Kontrollen innerhalb der Platten angeordnet.

+0

Vielen Dank! Eine einfache und elegante Lösung. Ich frage mich, warum es nicht so etwas wie "KeyPreview" für Mausklicks gibt –

Verwandte Themen