定义新的事件完全是比较少见。然而,当一个组件介绍行为是完全不同于任何其他组件不同,所以你需要为它定义一个事件。
当定义一个事件,还有一些问题你需要考虑:
触发事件(Triggering the event)
定义处理程序的类型 (Defining the handler type)
声明事件 (Declaring the event)
调用事件 (Calling the event)
触发事件
你需要知道什么触发了事件。对于某些事件,答案是显而易见的。例如,一个鼠标按下事件发生时,用户按下鼠标左键,然后Windows就会发送WM_LBUTTONDOWN消息给应用程序。在收到该消息,调用其组件的MouseDown方法,该方法又调用任何用户已连接到onMouseDown事件代码。
但是,一些不太清楚的事件绑定到特定的外部事件。例如,一个滚动条有一个OnChange事件,它是由数种的发生,包括按键,鼠标点击,并在其他控件的变化引起的。当定义你的事件,你必须确保所有适当的事件发生调用正确的事件处理代码。
定义处理程序的类型
一旦你确定当事件发生时,你必须定义要如何处理该事件。这意味着确定该事件处理程序的类型。在大多数情况下,你自己定义的事件的处理程序不是简单的通知或事件的具体类型。它也有可能从处理程序那得到信息反馈。
简单通知
通知事件是一个只有告诉你特定的事件发生了,不带有关何时何地的特定的信息。通知使用类型TNotifyEvent,事件的发送者仅带有一个参数。所有都是一对一的通知处理程序“知道”有关该事件的是什么样的事件,和什么组件的事件发生。例如,单击事件通知。当你写一个单击事件处理程序,所有你知道的是,一个点击发生了,并且知道哪个组件被点击了。
通知是单向的过程。没有机制来提供反馈或防止进一步处理的通知。
事件的具体处理程序
在某些情况下,知道哪些事件发生,它发生在什么组件,这样是不够的。例如,如果事件是一个按键事件,它是可能的处理程序将要知道用户按下哪个键。在这种情况下,就需要处理的类型得包括额外信息参数。
如果你的活动是响应消息生成,它是可能你传递给事件处理程序的参数,是直接来自消息参数。
从处理程序返回的信息
因为所有的事件处理程序是过程(procedure),只有通过一个var参数,才能从处理程序回传信息。您的组件可以使用这些信息来决定如何或是否要处理用户的处理程序执行后的事件。
例如,所有的(OnKeyDown,OnKeyUp和OnKeyPress)关键事件通过引用传递的参数名Key为按下键的键值。事件处理程序可以改变Key键值,以便让应用程序看作是不同的键值,然后再进行处理。例如,这是一种方法强迫输入的字符转换为大写。
声明事件
一旦你确定了你的事件处理程序的类型,您就可以声明方法指针和该事件的属性。务必给事件一个有意义的和描述性名称,以便用户可以了解事件一样。试着与在其他组件类似属性的名称一致。
事件名称开头“On”
在Delphi大多数事件的名称以“On“开头。这只是一个惯例,编译器不会强制要求。在Object Inspector确定某个事件属性,这看起来是属性的类型:所有的方法指针属性被认为是事件,并显示在事件Events页。
开发人员希望找到开头字母顺序排列的名称开始为“On“的事件。使用其他种类的名称可能会混淆他们。
调用事件
你应该集中调用一个事件。也就是说,在你创建一个组件,调用应用程序的事件处理程序(如果它分配一个),并提供任何默认处理虚拟方法。
确保在一个地方将所有的事件调用,有人从你的组件派生一个新的组件可以通过重写一个方法,而不是通过搜索你调用事件代码的地方。
调用事件时,有两方面需要考虑
*空的处理程序必须是有效的
*用户可以覆盖默认的处理
TNotifyEvent原型
TNotifyEvent = procedure(Sender: TObject) of object;
该TNotifyEvent事件类型是没有特定的事件参数类型。这些事件只是通知组件,一个特定的事件发生。例如,OnClick,它的类型是TNotifyEvent,通知在一个控件上发生了点击事件。
Sender参数是调用事件处理程序的对象。例如,使用一个按钮的OnClick事件,Sender参数是就是被点击的按钮组件。
自定义事件通常是应用程序与引用的单元文件的信息传递。下面一个例子说明,让应用程序自定义两个数的计算方式,可以为+、-、*、/等等,而内部的详细处理可以在单元文件里面实现,下面简要代码仅仅体现这种思想,具体根据实际修改:
1.新建Delphi 7应用程序,单击菜单栏→File→New→Unit,在弹出的单元文件,输入以下代码:
2.主窗体上放置2个编辑框和一个按钮,主单元文件代码如下:
3.运行程序,结果如下所示: