Originale-mail to me for new edition

 

Message methods

 

Message methods implement responses to dynamically dispatched messages. The message method syntax is supported on all platforms. The VCL uses message methods to respond to Windows messages. CLX does not use message methods to respond to system events.

A message method is created by including the message directive in a method declaration, followed by an integer constant between 1 and 49151 which specifies the message ID. For message methods in VCL controls, the integer constant can be one of the Windows message IDs defined, along with corresponding record types, in the Messages unit. A message method must be a procedure that takes a single var parameter.

For example, on Windows:

type

  TTextBox = class(TCustomControl)

  private

    procedure WMChar(var Message: TWMChar); message WM_CHAR;

    ...

  end;

For example, on Linux or for cross-platform programming, you would handle messages as follows:

const

  ID_REFRESH = $0001;

type

  TTextBox = class(TCustomControl)

  private

    procedure Refresh(var Message: TMessageRecordType); message ID_REFRESH;

    ...

  end;

A message method does not have to include the override directive to override an inherited message method. In fact, it doesn’t have to specify the same method name or parameter type as the method it overrides. The message ID alone determines which message the method responds to and whether it is an override.

 

Implementing message methods

The implementation of a message method can call the inherited message method, as in this example (for Windows):

procedure TTextBox.WMChar(var Message: TWMChar);

begin

  if Chr(Message.CharCode) = #13 then

    ProcessEnter

  else

    inherited;

end;

On Linux or for cross-platform programming, you would write the same example as follows:

procedure TTextBox.Refresh(var Message: TMessageRecordType);

begin

  if Chr(Message.Code) = #13 then

    ...

  else

    inherited;

end;

The inherited statement searches backward through the class hierarchy and invokes the first message method with the same ID as the current method, automatically passing the message record to it. If no ancestor class implements a message method for the given ID, inherited calls the DefaultHandler method originally defined in TObject.

The implementation of DefaultHandler in TObject simply returns without performing any actions. By overriding DefaultHandler, a class can implement its own default handling of messages. On Windows, the DefaultHandler method for VCL controls calls the Windows DefWindowProc function.

 

Message dispatching

Message handlers are seldom called directly. Instead, messages are dispatched to an object using the Dispatch method inherited from TObject:

procedure Dispatch(var Message);

The Message parameter passed to Dispatch must be a record whose first entry is a field of type Cardinal containing a message ID.

Dispatch searches backward through the class hierarchy (starting from the class of the object where it is called) and invokes the first message method for the ID passed to it. If no message method is found for the given ID, Dispatch calls DefaultHandler.

 

Topic groups

 

See also

About class types

Inherited

Methods: Overview

Overriding versus hiding

 

 

译文

 

消息方法

 

消息方法的实现是对动态调度的消息的响应。消息方法的语法支持所有的平台。VCL用消息方法响应Windows消息,而CLX不用消息方法响应系统事件。

消息方法由包括指示字message的方法声明创建,紧随一个介于1..49151之间用于指定消息ID的整数。在VCL消息方法的控制中,整数常量可以是Windows中定义过的消息ID(与Messages单元中相应的记录类型一起)。消息方法必需是一个过程,该过程只接受一个单独的var参数(在Windows中,该参数是一个整数;在Linux或跨平台应用中,该参数则是一个记录类型)。

 

例如,在Windows中:

type

  TTextBox = class(TCustomControl)

  private

    procedure WMChar(var Message: TWMChar); message WM_CHAR;

    ...

  end;

 

再如,在Linux或跨平台编程中,需要如下处理消息:

const

  ID_REFRESH = $0001;

type

  TTextBox = class(TCustomControl)

  private

    procedure Refresh(var Message: TMessageRecordType); message ID_REFRESH;

    ...

  end;

消息方法不必包括override指示字以覆盖继承得到的消息方法。实际上,没有必要指定相同的方法名或参数类型作为覆盖方法,消息ID唯一决定哪一个方法响应以及是否是一个覆盖方法。

 

实现消息方法

消息方法的实现可以调用继承的消息方法,如下面的例子(基于Windows):

procedure TTextBox.WMChar(var Message: TWMChar);

begin

  if Chr(Message.CharCode) = #13 then

    ProcessEnter

  else

    inherited;

end;

Linux或跨平台编程中,可以如下编写相同的例子:

procedure TTextBox.Refresh(var Message: TMessageRecordType);

begin

  if Chr(Message.Code) = #13 then

    ...

  else

    inherited;

end;

继承(inherited)语句向后(祖先方向)逐层搜索类并且调用找到的与当前方法具有相同消息ID的第一个消息方法,自动传递消息记录到找到的方法中。对给定的消息ID,如果没有祖先类为其实现消息方法,那么继承(inherited)语句会调用在TObject中定义的最初的DefaultHandler方法。

TObject类中DefaultHandler方法的实现只是简单地返回而没有指定任何动作。通过覆盖DefaultHandler方法,一个类可以实现其自身缺省的信息处理。在Windows中,用于VCL控制的DefaultHandler方法调用的是WindowsDefWindowProc函数。

 

消息调度

消息处理程序很少被直接调用,消息调度由对象通过继承自TObjectDispatch方法类实现。

procedure Dispatch(var Message);

这里,传递到DispatchMessage参数必需是一个记录,该记录的首项是一个包含了消息IDCardinal类型的字段。

Dispatch方法向后(祖先方向)逐层搜索(从给方法被调用的对象所属的类开始),并且调用第一个与当前消息ID匹配的消息方法。对于给出的ID,如果没有发现相应的消息方法,那么Dispatch方法将调用DefaultHandler

 

主题组

 

相关主题

关于类类型

继承(Inherited

方法:概述

覆盖和隐藏