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.
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 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.
消息方法的实现是对动态调度的消息的响应。消息方法的语法支持所有的平台。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方法调用的是Windows的DefWindowProc函数。
消息处理程序很少被直接调用,消息调度由对象通过继承自TObject类Dispatch方法类实现。
procedure Dispatch(var
Message);
这里,传递到Dispatch的Message参数必需是一个记录,该记录的首项是一个包含了消息ID的Cardinal类型的字段。
Dispatch方法向后(祖先方向)逐层搜索(从给方法被调用的对象所属的类开始),并且调用第一个与当前消息ID匹配的消息方法。对于给出的ID,如果没有发现相应的消息方法,那么Dispatch方法将调用DefaultHandler。