Delphi 7事件的多处理机制
Delphi 7事件的多处理机制
Allen Tao
2007-08-19
首先解释一下这个题目。在我使用Delphi 7的过程中发现,一个对象的事件只能被一个过程处理。如果多次给这个对象的事件赋给处理事件的过程,最后真正处理事件的将是最后赋值的那个过程。例如,有类TMyClass中定义了一个事件OnSomeFired,在类TClientClass中该类被实例化,它的事件被处理。如下所示:
constructor TClientClass.Create;
var
myObj: TMyClass;
begin
//…
myObj:= TMyClass.Create;
myObj.OnSomeFired:= SomeFired1;
myObj.OnSomeFired:= SomeFired2;
这里的SomeFired1与SomeFired2都是TClientClass中定义的处理过程。其最终的结果是当OnSomeFired事件发生时,只有SomeFired2被调用。
但在编程的实际中,往往需要一个事件被多个方法所处理。为此,我参考了一些对这个问题的解决办法,总结得出了一个自己的方法,称为事件的多处理机制。
原理
Delphi 7中的事件本质上是一种过程指针。但事件类型在定义时要比一般过程指针在最后多一个“of object”,如常用的TNotifyEvent的定义是:
TNotifyEvent = procedure(Sender: TObject) of object;
因此,给一个事件属性赋值,也就是给一个类的过程指针类型的成员变量赋值,当然是最后一次的赋值才有效。要想多次赋值有效就必须有一个数据结构把每次赋值赋给的过程指针变量都记录下来,最合适的数据结构当然是列表TList。但如果在每一个有事件的类中都加一个记录事件赋值的列表对象,自然是不方便的,而且使用这个列表的代码在不同类中也差不多,应该抽取出来形成一个类。这个类就是事件多处理机制的核心内容。
做法
要记录事件处理过程,就需要将过程指针变量放入列表对象中。但列表对象只能添加指针类型对象(也就是引用类型),而过程指针变量是指类型变量,不能直接添加。这就需要有一个类对过程指针变量进行包装,转化为指针类型对象。于是,先要定义包装类TCallMethod,如下所示:
TCallMethod = class
private
_callback: TMethod;
public
property Callback: TMethod read _callback write _callback;
end;
这里的TMethod是Delphi预定义的记录类型,任何过程指针变量都可以强制转化为这种类型。之后,再定义记录处理过程的类,如下所示:
TEve
相关文档:
Delphi键盘按键伪码
用法:if key = chr(VK_RETURN) then...
常数名称 十六进制值 十进制值 对应按键
VK_LBUTTON 01 1 鼠标的左键
VK_RBUTTON 02 2 鼠标的右键
VK-CANCEL 03 3 Contol-break 执行
VK_MBUTTON 04 4 鼠标的中键(三按键鼠标)
VK_BACK 08 8 Backspace键
VK_TAB 09 9 Tab键
VK_CLEAR 0C 12 Clear键
VK ......
Delphi 数据类型列表
分类
范围
字节
备注
简单类型
序数
整数
Integer
-2147483648 .. 2147483647
4
有符号32位
Cardinal
0 .. 4294967295
4
无符号32位
Shortint
-128 .. 127
1
有符号8位
Smallint
-32768 .. 32767
2
有符号16位
Longint
-2147483648 .. 2147483647
4
有符号32位
Int64
- ......
var
L,i:integer;
Ustr,str:string;
p:char;
begin
str:='123456789ABCDEFG'
L:=length(str);
for i:=1 to l do begin
p:=str[i];
str[i]:=str[l-(i-1)];
......
Delphi编写系统服务三:编写两栖系统服务 收藏
采用下面的方法,可以实现一个两栖系统服务(既系统服务和桌面程序的两种模式)
工程代码:
program FleetReportSvr;
uses
SvcMgr,
Forms,
SysUtils,
Windows,
SvrMain in 'SvrMain.pas' {FleetReportService: TService}, ......
procedure Delay(msecs:integer);
var
Tick: DWord;
Event: THandle;
begin
Event := CreateEvent(nil, False, False, nil);
try
Tick := GetTickCount + DWord(msecs);
while (msecs > 0) and (MsgWaitForMultipleObjects(1, Event, False, msecs, QS_ALLINPUT) <&g ......