2008-10-07 8 views
5

저는 C# 형식 (사용자 정의 컨트롤이있는 MainForm)을 사용하고 있습니다. 폼에서 클릭이 발생했는지 또는 클릭이 사용자 정의 컨트롤 중 하나에 있었는지에 관계없이 누군가가 폼을 클릭 할 때마다 MainForm.OnClick() 메서드가 실행되도록하고 싶습니다. 나는 키 누르기보다는 마우스 클릭을 제외하고 폼의 KeyPreview 기능과 비슷한 동작을 찾고있다.양식에 클릭 이벤트를 설정하려면 어떻게해야합니까?

답변

2

폼의 ControlAdded 이벤트에서 폼의 Click 이벤트의 Address를 사용하여 MouseClick 처리기를 컨트롤에 추가합니다. 나는 이것을 시험하지는 않았지만 효과가있을 것이다.

+0

이것은 여전히 ​​약간의 해킹 인 것처럼 보이지만 이것은 내가 가진 최선의 선택 인 것 같습니다. – Mykroft

0

양식의 열린 공간에서 클릭을 잡아내는 것은 쉽지만 실제로 컨트롤에있는 클릭을 얻으려면 해당 컨트롤과 협력하여 양식으로 보내야합니다.

하나의 가능성은 전체 양식에 대해 투명한 컨트롤을 배치하고 클릭을 받아 들여 처리 한 다음 해당 컨트롤 바로 아래로 전달하는 것입니다.

+0

나는 이보다 더 우아한 해결책이 있어야한다고 생각합니다. – Mykroft

1

내가 수행 한 유일한 방법은 모든 컨트롤의 [c] 클릭 [/ c] 이벤트를 처리하는 것입니다. 컨트롤이 처리하기 전에 이벤트가 발생했다고 생각하지 않습니다.

WPF에서는이 기능을 제공하는 "터널링"미리보기 이벤트가 있지만 WinForms에서는 도움이되지 않습니다.

+0

글쎄, WPF로 전환하기에는 너무 늦었지만, 미래에 사용하는 것을 진지하게 고려해야 할 것입니다. – Mykroft

1

원하는 경우 모든 컨트롤의 이벤트를 연결 한 다음 해당 방식으로 모니터링 할 수 있습니다. 나는 그 (것)들을 모두 함정에 빠뜨리기 위하여 어떤 위버 공상 Win32 API 방법이다는 것을 추측한다, 그러나 저 저 순간 저 순간이다.

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 :

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

출력은 모든 이벤트 누가 그들을 "전송"을 보여주는이 같은 것입니다.

6

응용 프로그램에서 상속 할 다른 폼에 대한 기본 폼을 만드는 것이 좋습니다. 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); 
      } 
     } 
    } 
} 

이 솔루션뿐만 아니라 최상위 컨트롤 작동하지만 또한 패널의 내부에 위치 컨트롤로 컨트롤을 중첩됩니다.

+0

감사합니다. 간단하고 우아한 솔루션. 마우스 클릭에 대해 'KeyPreview'와 동일한 기능이없는 이유가 궁금합니다. –

관련 문제