按钮事件之我见

来源:互联网 发布:淘宝电子面单怎么充值 编辑:程序博客网 时间:2024/04/28 05:42
按钮事件之我见
作者jim
时间2006-6-21
关键词:虚函数(virtual)、覆盖(override)、事件(event)、代理(delegate
引言:在面向对象的程序设计中,主要涉及到的关键知识点就是以上列出的几个,在学习过程中,往往是分散开来学习,可能会出现学前忘后的现象,本文主要通过c#中对一个按钮(button)的继承的实例说明,了解各自的用法和内部联系。由于本人知识有限,如若出现错误之处,还望各位大虾指正。小弟在此先谢过。J
 
前言说明:相信各位在系统开发过程中,肯定使用过按钮(button)。在使用过程中可能就是从工具箱中拖动一个button到窗体中,在双击按钮,自动编写按钮的click事件代码,不费吹会之力就可完成按钮使用,但是,在系统的内部他是怎么工作的呢?相信深入探讨和研究的可能就比较少了吧,:)以下就是小弟,经过粗浅的研究后得到的一点启发,现整理出来供大家一起参考,以达到抛砖引玉的作用。
 
初步分析:当我们将一个按钮从工具箱中拖到我们的窗体中时,其实在窗体的designer.cs中则首先生成了一行此按钮的引用:
private System.Windows.Forms.Button sysbtn;
sysbtn是我的button的名称,请注意此时sysbtn的类型说明,后面说明中会涉及到。
当我们需要进行对该按钮的单击事件需要编码时,我们只需要双击一下这个按钮即可自动出现一个函数供我们填写。
private void sysbtn_Click(object sender, EventArgs e)
{
    MessageBox.Show("这是系统按钮的事件委托");
}
其实在在窗体的designer.cs中,会自动生成事件的具体定义和说明
this.sysbtn.Click += new System.EventHandler(this.sysbtn_Click);
 
现在对这一行文字进行解释和说明:
首先是事件this.sysbtn.Click,我们知道Clickbutton一个事件,他只是button类中N个事件中的一个,但他们都具有相同的性质和用法,即:事件都是由定义事件的类自生触发,并在类的外部实现具体的事件处理。
 
然后是代理(delegate,代理其实就是一个指针函数,他规定了事件的原型定义,如代理名称、代理参数,对于以上的buttonclick事件的代理已经由c#编译系统预定义了,就是System.EventHandlerEventArgs e),代理其实起了一个桥梁的作用,通过代理,将类内部事件与类外部处理衔接起来。
 
最后是外部事件处理在本例中,外部处理即:
private void sysbtn_Click(object sender, EventArgs e)
{
    MessageBox.Show("这是系统按钮的事件委托");
}
事件外部处理函数原型必须与代理一致。此处单击按钮时,会显示"这是系统按钮的事件委托"消息框。
 
深入分析:现在我们深入到button的内部,再次研究一下click事件的工作原理,通过前面的描述,我们了解到事件是在类内部触发的,但是具体是什么东西触发了呢?
  我们通过msdn帮助可了解到button类的所有成员的组成,会发现其中有个protected virtual void OnClick( EventArgs e)  函数,从函数名称我们可以看出他与Click事件有着必然的联系,其实,元凶就是他,是他触发了buttonclick事件,我们可以通过以下的实例进行验证,下面我们来具体分析一下:
 
首先是虚函数(virtual),虚函数的主要特点就是用来被继承类覆盖的,在后面的说明中,我们就会发现他的奥妙所在了。
 
然后我们通过继承button类,生成我们自己的buttonmybtn
class mybtn :System.Windows.Forms.Button
{    
}
 
并在刚才的窗体中引用我们的button类,和事件定义以及实现函数
private mybtn mybtn;
this.mybtn.Click += new System.EventHandler(this.mybtn_Click);
private void mybtn_Click(object sender, EventArgs e)
{
     MessageBox.Show("这是我的按钮的事件委托");
}
显然,当单击按钮时,也会显示"这是我的按钮的事件委托"消息框。
 
下一步,为了发掘protected virtual void OnClick( EventArgs e)的奥妙,我们在mybtn类中覆盖此函数,并实现了显示"mybtn是从System.Windows.Forms.Button继承而来,触发了click事件,但系统代理已经失效"的功能。
class mybtn :System.Windows.Forms.Button
{
        protected override void OnClick( EventArgs e) 
        {
            MessageBox.Show("mybtn是从System.Windows.Forms.Button继承而来,触发了click事件,但系统代理已经失效");
        }
 }
现在我们再单击我们的按钮,猜猜,会发生什么情况,是显示几个消息框呢?0个?一个?二个?
 
 
答案是,只显示了一个消息框,"mybtn是从System.Windows.Forms.Button继承而来,触发了click事件,但系统代理已经失效",他并没有触发到我们外部定义的消息处理过程:
private void mybtn_Click(object sender, EventArgs e)
{
     MessageBox.Show("这是我的按钮的事件委托");
}
由此我们就可以发现,buttonclick事件是由OnClick函数来触发的,由此我们会产生一个问题,当继承了button类后,我们怎么才能让他也能触发click事件呢?
很简单,我们只需要在我们覆盖的OnClick函数中再调用一下基类中的OnClick函数即可。
class mybtn :System.Windows.Forms.Button
 {
        protected override void OnClick( EventArgs e) 
        {
            MessageBox.Show("mybtn是从System.Windows.Forms.Button继承而来,触发了click事件,但系统代理已经失效");
            base.OnClick(e);
        }
 }
一切OK了!
是由基类的OnClick函数来触发click事件,至于基类的OnClick是怎么触发的,那就得问微软的人了。J
 
总结:通过以上的实例我们可以对事件进行总结:类的某个事件是在其内部触发,往往是由一个虚函数触发。类事件通过代理与外部的处理函数相关联,由用户来实现自己的事件处理过程。
 
 
原创粉丝点击