C#
消息不能向下传递,上层控件处理了就不能往下传了,这对于整个窗体都要处理鼠标、个别控件有特殊处理这样的模式就有些麻烦
窗体里面每个控件都要设置事件代码,如果有遗漏编译不会出问题,很难发现
所以要用代码来给所有控件增加事件代码,从而等价实现了向下传播鼠标消息
入口是Control,对于Form可以直接用this,如果不需要整个窗体范围就用一个容器替代,针对的是MouseDown消息
FormEntry_MouseDown是Form的事件MouseDown的处理程序,通过窗体设计器添加的
myInit_AddEvent(this)可以将这个事件处理程序绑定到所有的子控件
1 void myInit_AddEvent(Control control) 2 { 3 foreach (Control v in control.Controls) 4 { 5 //判断是否已经设置了MouseDown,已经设置了则不再设置 6 PropertyInfo pi = typeof(Control).GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); 7 EventHandlerList ehl = (EventHandlerList)pi.GetValue(v, null); 8 FieldInfo fieldInfo = (typeof(Control)).GetField("EventMouseDown", BindingFlags.Static | BindingFlags.NonPublic); 9 Delegate d = ehl[fieldInfo.GetValue(null)]; 10 11 if (null == d) 12 { 13 //MessageBox.Show(v.ToString() + " null"); 14 } 15 else 16 { 17 foreach (Delegate del in d.GetInvocationList()) 18 {//这个循环没什么用,只是演示了如何判断事件处理程序的名字 19 //MessageBox.Show(v.ToString() + " " + del.Method.Name); 20 if (del.Method.Name == "FormEntry_MouseDown")//这是事件处理程序的名字,可以单独写,也可以直接使用已经存在的事件处理程序 21 { 22 continue; 23 } 24 } 25 if (d.GetInvocationList().Length > 0) continue;//这里判断的是如果设置过任何一个事件处理程序就不设置了。严格地讲,别的代码可能处于别的需要设置了事件处理程序,应该判断具体的名字 26 } 27 v.MouseDown += new MouseEventHandler(FormEntry_MouseDown);//设置事件处理程序 28 myInit_AddEvent(v);//递归设置子控件 29 } 30 }