Office中国论坛/Access中国论坛
标题:
【原创】RibbonButton点击事件的真实原理
[打印本页]
作者:
faunus
时间:
2014-3-9 16:01
标题:
【原创】RibbonButton点击事件的真实原理
本帖最后由 faunus 于 2014-3-13 13:29 编辑
处理流程如下:
// MyButton.MyClick的真实处理情况是这样的:
// 首先,向外公布一个MyClick方法变量,对这个变量的操作支持add和remove操作.
// 当Add操作时(也就是从外边作+=操作时),将传入值写入一个列表,起个名字叫做事件列表.
// 在MyButton内部的消息处理过程WndProc中,当截获到WM_LBUTTONUP消息时,调用WmMouseUp方法处理.
// 在WmMouseUp实体中调用MyOnClick方法.
// 在MyOnClick实体中,从事件列表中取到方法实例handler并调用方法.
// MyButton.MyClick的工作原理与例4所描述的不同
// 1.方法变量MyClick没有直接用来存放外部的方法实例,而是象属性那样,存放在一个字段_myEvents中.
// 2.消息处理过程WndProc也没有MyClick的调用,而是在MyOnClick中调用方法字段.
// 从本质上讲WndProc还是处理了MyClick的,但实现思路上区别很大.
// 好像少了一个环节,MyClick在内部没实例化过.MyOnClick中进行了方法字段是否为空的判断.
// 这说明方法变量在内部不一定需要传入实例,只要内部调用时进行非空判断就可以了.
// 以上研究都是把方法变量当做一般变量来处理.
// delegate与消息循环结合,这就是我们看到的事件.
// 事件带来的效果,实现了一个对象将自己的方法公布给别人,并由别人进一步完善这个方法.
// 这又绕回到最开始举的例子:领导委托下属做某件事!
// 最初的例子委托用错了地方,把下属的方法定义了一个变量来调用.
// 应该是把领导这个对象内定义一个方法变量,由下属具体实现.
// 下一例重构最初的例子.
复制代码
消息处理过程如下:
【重载消息中心】
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_LBUTTONUP:
this.WmMouseUp(ref m, System.Windows.Forms.MouseButtons.Left, 1);
break;
}
}
复制代码
【加工消息参数】
private void WmMouseUp(ref Message m, System.Windows.Forms.MouseButtons button, int clicks)
{
//验证状态、将传入的消息加工成事件参数
// ...
MouseEventArgs args = new MouseEventArgs(button, clicks, SignedLOWORD(m.LParam), SignedHIWORD(m.LParam), 0);
this.MyOnClick(args);
}
复制代码
【辅助函数】
private int SignedLOWORD(IntPtr n)
{
return (short)((int)((long)n) & 0xffff);
}
private int SignedHIWORD(IntPtr n)
{
return (short)(((int)((long)n) >> 0x10) & 0xffff);
}
复制代码
事件的定义部分:
【消息字段声明】
const int WM_LBUTTONUP = 0x202;
#region "字段声明"
EventHandlerList _myEvents;
object _eventClick = new object();
#endregion
复制代码
【事件的定义】
#region "属性定义"
public EventHandlerList MyEvents
{
get
{
if (this._myEvents == null)
{
this._myEvents = new EventHandlerList();
}
return this._myEvents;
}
}
#endregion
#region "事件定义"
public event EventHandler MyClick
{
add
{
Events.AddHandler(_eventClick, value);
}
remove
{
Events.RemoveHandler(_eventClick, value);
}
//AsyncCallback
//Activator
}
#endregion
复制代码
【调用方法】
private void MyOnClick(EventArgs e)
{
EventHandler handler = (EventHandler)base.Events[_eventClick];
if (handler != null)
{
handler(this, e);
}
}
复制代码
注意:这里的handler是一个委托,将执行所有注册方法的列表。
附件(完整代码):
[attach]53521[/attach]
作者:
紫电
时间:
2014-3-10 11:52
没有内容,弄没了吧
作者:
tmtony
时间:
2014-3-10 21:15
是没有看到内容
作者:
smrgh
时间:
2014-3-11 17:00
???
作者:
醉酒狂生
时间:
2014-3-11 17:07
老大是在逗我们玩?
作者:
ET_ET
时间:
2014-3-13 12:34
隐身可见?
作者:
Amas
时间:
2014-3-13 13:48
留个足迹,待日后学习.
作者:
yjjcm
时间:
2014-3-13 14:07
占个位,便于以后查询
作者:
llm4947
时间:
2015-1-9 20:45
#在这里快速回复#没有内容,弄没了吧
欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/)
Powered by Discuz! X3.3