【问题标题】:Catching a Contained Control's Mouse Events in a UserControl在 UserControl 中捕获包含控件的鼠标事件
【发布时间】:2011-03-17 03:59:25
【问题描述】:

我有一个UserControl,其中包含另一个UserControl。我希望包含控件能够处理在包含控件区域上发生的任何鼠标事件。最简单的方法是什么?

更改包含控件的代码是可能的,但只能作为最后的手段。包含的控件有一个由非托管库控制的窗口。

FWIW,我尝试为包含的控件的鼠标事件添加处理程序,但这些处理程序从未被调用。我怀疑包含的控件正在消耗鼠标事件。

我考虑在包含的控件之上添加某种透明窗口以捕获事件,但我对 Windows 窗体还是很陌生,我想知道是否有更好的方法。

【问题讨论】:

    标签: .net winforms user-controls


    【解决方案1】:

    如果内部控件未密封,您可能希望对其进行子类化并覆盖与鼠标相关的方法:

    protected override void OnMouseClick(MouseEventArgs e) {
        //if you still want the control to process events, uncomment this:
        //base.OnMouseclick(e)
    
        //do whatever
    }
    

    等等

    【讨论】:

      【解决方案2】:

      嗯,这在技术上是可行的。您必须自己重定向鼠标消息,这需要一些 P/Invoke。将此代码粘贴到您的内部 UserControl 类中:

          protected override void WndProc(ref Message m) {
              // Re-post mouse messages to the parent window
              if (m.Msg >= 0x200 && m.Msg <= 0x209 && !this.DesignMode && this.Parent != null) {
                  Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
                  // Fix mouse position to be relative from parent's client rectangle
                  pos = this.PointToScreen(pos);
                  pos = this.Parent.PointToClient(pos);
                  IntPtr lp = (IntPtr)(pos.X + pos.Y << 16);
                  PostMessage(this.Parent.Handle, m.Msg, m.WParam, lp);
                  return;
              }
              base.WndProc(ref m);
          }
      
          [System.Runtime.InteropServices.DllImport("user32.dll")]
          private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
      

      顺便说一句,最好避免这样做。父控件应该只订阅内部控件的鼠标事件。

      【讨论】:

        【解决方案3】:

        这就是我所做的:

        首先,我定义了一个TransparentControl 类,它只是一个透明且不绘制任何内容的控件。 (此代码感谢https://web.archive.org/web/20141227200000/http://bobpowell.net/transcontrols.aspx。)

        public class TransparentControl : Control
        {
            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
                    return cp;
                }
            }
        
            protected override void OnPaint(PaintEventArgs pe)
            {
                // Do nothing
            }
        
            protected override void OnPaintBackground(PaintEventArgs pevent)
            {
                // Do nothing
            }
        }
        

        然后,我在包含的用户控件之上的用户控件中放置了一个TransparentControl,并为其鼠标事件添加了处理程序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-26
          相关资源
          最近更新 更多