荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: Delphi自定义部件(四)
发信站: BBS 荔园晨风站 (Fri Jan 22 13:46:29 1999), 转信



19.2.2.2 创建事件

  事件是部件的很重要的部分。事件是部件必须响应的系统事件与响应事件的一段代码
的联接。响应代码被称为事件处理过程,它总是由部件用户来编写。通过使用事件,应用
开发者不需要改变部件本身就能定制部件的行为。作为部件编写者,运用事件能使应用发
者定制所有的标准Delphi部件。要创建事件,应当理解:
   ● 什么是事件
   ● 怎样实现标准事件
   ● 怎样定义自己的事件

  1. 什么是事件
    事件是联接发生的事情与某些代码的机制,或者说是方法指针,一个指向特定对象实
例的特定方法的指针。从部件用户的角度,事件是与系统事件(如OnClick)有关的名称,用
户能给该事件赋特定的方法供调用。例如,按钮Buttonl有OnClick方法,缺省情况下Delphi
在包含该按钮的窗体中产生一个为ButtonlClick的方法,并将其赋给OnClick。当一个Click
事件发生在按钮上时,按钮调用赋给OnClick的方法ButtonlClick:





                    图19.3  Delphi 应用程序事件流程

    部件用户将事件看作是由用户编写的代码,而事件发生时由系统调用的处理办法。
  从部件编写者角度事件有更多的含义。最重要的是提供了一个让用户编写代码响应特
定事情的场所。
  要编写一个事件,应当理解:
   ● 事件和方法指针
   ● 事件是属性
  ● 事件处理过程类型
   ● 事件处理过程是可选的

  ⑴ 事件是方法指针
  Delphi使用方法指针实现事件。一个方法指针是指向特定对象实例的特定方法的特定
指针。作为部件编写者,能将方法指针作为一种容器。你的代码一发现事情发生,就调用
由用户定义的方法。
  方法指针的工作方式就象其它的过程类型,但它们保持一个隐含的指向对象实例的指
针。所有的控制都继承了一个名为Click的方法,以处理Click事件。Click方法调用用户
的Click事件处理过程。

  procedure TControl.Click;
     begin
       if Assigned(OnClick ) then OnClick( Self );
     end;

    如果用户给Control的OnClick事件赋了处理过程(Handle),那鼠标点按Control时将导
致方法被调用。
  ⑵ 事件是属性
  部件采用属性的形式实现事件。不象大多数其它属性,事件不使用方法来使实现read
和write部分。事件属性使用了相同类型的私有对象域作为属性。按约定域名在属性名前加
“F”。例如OnClick方法的指针,存在TNotifyEvent类型FOnClick域中。OnClick事件
属性的声明如下:

    type
      TControl=class ( TComponent )
      private
        FOnClick: TNofiFyEvent;  { 声明保存方法指针的域 }
      protected
        property OnClick: TNotifyEvent read FOnClick write FOnClick;
      end;

   象其它类型的属性一样,你能在运行时设置和改变事件的值。将事件做成属性的主要
好处是部件用户能在设计时使用Object Inspector设置事件处理过程。
  ⑶ 事件处理过程类型
  因为一个事件是指向事件处理过程的指针,因此事件属性必须是方法指针类型,被用
作事件处理过程的代码,必须是相应的对象的方法。
  所有的事件方法都是过程。为了与所给类型的事件兼容,一个事件处理过程必须有相
同数目和相同类型的相同顺序的参数。Delphi定义了所有标准事件处理过程的方法类型,
当你创建自己的事件时,你能使用已有的事件类型,或创建新的。虽然不能用函数做事件
处理过程,但可以用var参数得到返回信息。
  在事件处理过程中传递var参数的典型例子是TKeyPressEvent类型的KeyPressed事
件。TKeyPressEvent定义中含有两个参数。一个指示哪个对象产生该事件。另一个指示那
个键按下:

  type
      TKeyPressEvent=procedure( Sender: TObject; var key: char) of Object;

    通常key参数包含用户按下键的字符。在某些情况下,部件的用户可能想改变字符值。
例如在编辑器中强制所有字符为大写,在这种情况下,用户能定义下列的事件处理过程:

   procedure TForml.EditlKeyPressed( Sender: TObject; var key: char);
     begin
       key := Upcase( key );
     end;

    也可使用var参数让用户覆盖缺省的处理。
  ⑷ 事件处理过程是可选的
  在为部件创建事件时要记住部件用户可能并不编写该事件的处理过程。这意味着你的
部件不能因为部件用户没有编写处理代码而出错。这种事件处理过程的可选性有两个方
面:
  ① 部件用户并非不得不处理事件
    事件总是不断地发生在Windows应用程序中。例如,在部件上方移动鼠标就引起
Windows发送大量的Mouse-Move消息给部件,部件将鼠标消息传给OnMouseMove事件。
在大多数情况下,部件用户不需要关心MouseMove事件,这不会产生问题,因为部件不依
赖鼠标事件的处理过程。同样,自定义部件也不能依赖用户的事件处理过程。
   ② 部件用户能在事件处理过程写任意的代码
  一般说来,对用户在事件处理过程中的代码没有限制。Delphi部件库的部件都支持这
种方式以使所写代码产生错误的可能性最小。显然,不能防止用户代码出现逻辑错误。
  2. 怎样实现标准事件
  Delphi带的所有控制继承了大多数Windows事件,这些就是标准事件。尽管所有这些
事件都嵌在标准控制中,但它们缺省是protected,这意味着用户无法访问它们,当创建控
制时,则可选择这些事件使用户可用。将这些标准事件嵌入自定义控制需要考虑如下:
  ● 什么是标准事件
   ● 怎样使事件可见
   ● 怎样修改标准事件处理过程

  ⑴ 什么是标准事件
  有两种标准事件:用于所有控制和只用于标准Windows控制。
  最基本的事件都定义在对象TControl中。窗口控制、图形控制和自定义控制都继承了
这些事件,下面列出用于所有控制的事件:
  OnClick  OnDragDrop  OnEndDrag  OnMouseMove
   OnDblClick  OnDragOver  OnMouseDown  OnMouseUp

  所有标准事件在TControl中都定义了相应的protected动态方法,只是没有加“On”
例如OnClick事件调用名为Click的方法。
  标准控制(从TWinControl继承)具有下列事件:
     OnEnter  OnKeyDown  OnkeyPress  OnKeyUp  OnExit

    正如TControl中的标准事件,窗口控制也有相应protected动态方法。
  ⑵ 怎样使事件可见
  标准事件的声明是protected,如果想使用户在运行时或设计时能访问它们,就需要将
它们重声明为public和 published。重声明属性而不描述它的实现将继承相同的实现方法,
只是改变了访问级别。例如,创建一个部件并使它的OnClick事件出现在运行时,你可增
加下面的部件声明:

  type
      TMyControl=class(TCustomControl)
      published
        property OnClick;  { 使OnClick在objectinspector中可见 }
      end;

    ⑶ 怎样修改标准事件处理过程
  如果想修改自定义部件响应某种事件的方法,可以重写代码并将其赋给事件。将联接
每个标准事件的方法声明的protected是出于慎密的考虑。通过,覆盖实现方法,能修改内
部事件处理过程,通过调用继承的方法,能保持标准事件处理过程。
  调用继承的方法的顺序是很重要的。一般首先调用继承的方法,允许用户的事件处理
过程代码在你的定制代码前执行。然而也有在调用继承的方法之前执行自己的代码情况出
现。

  下面是一个覆盖Click事件的例子:

    procedure TMyControl.Click;
    begin
      inherited Click;  { 执行标准处理,包括调用事件处理过程你自己的定制代码 }
    end;

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店