2008-10-07 9 views
5

Mam formularz C# (nazwijmy go MainForm) o liczbie kontroli celnych na nim. Chciałbym, aby metoda MainForm.OnClick() była uruchamiana za każdym razem, gdy ktoś kliknie w formularz, niezależnie od tego, czy kliknięcie nastąpiło w formularzu, czy też kliknięcie dotyczyło jednego z elementów sterujących. Szukam zachowania podobnego do funkcji KeyPreview w formularzach z wyjątkiem kliknięć myszy, a nie naciśnięć klawiszy.Jak ustawić zdarzenie kliknięcia dla formularza?

Odpowiedz

2

W zdarzeniu ControlAdded formularza dodaj handler MouseClick do formantu, za pomocą opcji Adres zdarzenia kliknięcia formularza. Nie testowałem tego, ale to może zadziałać.

Private Sub Example_ControlAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles Me.ControlAdded 

    AddHandler e.Control.MouseClick, AddressOf Example_MouseClick 
End Sub 

Private Sub Example_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick 
    MessageBox.Show("Click") 
End Sub 
+0

To wciąż wydaje się być trochę hackerem, ale wydaje mi się, że to najlepsza opcja, jaką mam. – Mykroft

0

Catching kliknij na otwartej przestrzeni na formularzu jest łatwe, ale żeby kliknięcie, która jest faktycznie na kontrolę, trzeba współpracy tej kontroli, aby wysłać go do formy.

Jedną z możliwości jest umieszczenie przejrzystą kontrolę nad całym formie i zaakceptować kliknięć na tym, radzenia sobie z nimi, a następnie przekazać je na właściwej kontroli pod spodem.

+0

Mam wrażenie, że musi być bardziej eleganckie rozwiązanie niż to. – Mykroft

1

Jedynym sposobem, jaki kiedykolwiek udało się to zrobić, aby obsłużyć [c] Kliknij [/ c] wydarzeniem każdej kontroli. Nie wierzę, że wydarzenie zostanie podniesione, zanim kontrola go przetworzy.

W WPF, istnieje „tunelowania” Podgląd zdarzeń, które zapewniają tę funkcjonalność, ale to nie naprawdę pomóc w WinForms.

+0

Cóż, jest za późno, aby przejść do WPF teraz, ale będę musiał poważnie rozważyć użycie go w przyszłości, jak sądzę. – Mykroft

1

można podłączyć wszystkie zdarzenia formantu, jeśli chcesz, a następnie monitorować w ten sposób. Zakładam, że jest jakaś popularna metoda Win32 api, aby uwięzić je wszystkie, ale w tej chwili jest to poza mną.

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 
      ); 
    } 

Wyjście jest coś takiego, pokazując wszystkie zdarzenia i kto "Wysłane" je:

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

Zalecam utworzenie formularza podstawowego dla innych formularzy w aplikacji do dziedziczenia. Dodaj ten kod do swojej formie podstawowej, aby stworzyć nowe wydarzenie o nazwie GlobalMouseClickEventHandler:

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); 
      } 
     } 
    } 
} 

Takie rozwiązanie będzie działać nie tylko dla kontroli najwyższego poziomu, ale również zagnieżdżone elementy sterujące takie jak kontrolnych umieszczonych wewnątrz paneli.

+0

Dzięki za tonę! Proste i eleganckie rozwiązanie. Zastanawiam się, dlaczego nie ma czegoś podobnego do 'KeyPreview' dla kliknięć myszą –

Powiązane problemy