Delphi 7事件的多处理机制

Delphi程序设计之--经验技巧 这些日子太忙了,今天把剩下的部分贴完,希望对大家有用。看过前一篇的都知道此文的作者和出处,我就不详细说了。{ No. 16 }//对于记录类型Record的分析。实例:type TBaseRec = record   rStr: Integer;   rStr2: String;   rStr3: String; end; TStrRec = record   rStr: Integer 阅读详情


 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预定义的记录类型,任何过程指针变量都可以强制转化为这种类型。之后,再定义记录处理过程的类,如下所示:
  TEventObject = class
  private
    callList: TList;
    function GetItem(i: Integer): TMethod;
    function GetCount: Integer;
  public
    constructor Create;

    procedure Add(p: TMethod);
    procedure Remove(p: TMethod);

    property Count: Integer read GetCount;
    property Items[i: Integer]: TMethod read GetItem;  default;
  end;
  下面是实现部分:
constructor TEventObject.Create;
begin
  callList:= TList.Create;
end;

procedure TEventObject.Add(p: TMethod);
var
  a: TCallMethod;
begin
  a:= TCallMethod.Create;
  a.Callback:= p;
  callList.Add(a);
end;

procedure TEventObject.Remove(p: TMethod);
var
  i: Integer;
begin
  for i:= 0 to GetCount - 1 do
    if (TCallMethod(callList[i]).Callback.Code = p.Code) and
      (TCallMethod(callList[i]).Callback.Data = p.Data) then
      callList.Delete(i);
end;

function TEventObject.GetCount: Integer;
begin
  Result:= callList.Count;
end;

function TEventObject.GetItem(i: Integer): TMethod;
var
  a: TCallMethod;
begin
  a:= TCallMethod(callList[i]);
  Result:= a.Callback;
end;
  从上面的代码可以看到,TEventObject的目的是包装TList对象,屏蔽了TList类的大多数方法,只对外暴露了2个过程、1个属性与1个索引,分别用于添加、删除处理事件过程、获得过程个数及通过序号检索记录的过程变量。

使用
  使用时,在需要使用事件的类中将事件的类型由过程指针改为TEventObject,即可使该事件拥有多处理的能力。如下面代码所示:
  TMyClass=class
  private
    someFired: TEventObject;
  public
    constructor Create;
    procedure DoSth;
    property OnSomeFired: TEventObject read someFired write someFired; // 多处理事件
  end;
  以下是实现代码:
constructor TMyClass.Create;
begin
  Self.someFired:= TEventObject.Create;
end;

procedure TMyClass.DoSth;
var
  i: Integer;
  method: TNotifyEvent;
begin
  if someFired.Count > 0 then
    for i:= 0  to someFired.Count - 1 do
    begin
      method:= TNotifyEvent(someFired[i]); // 在该类中事件的真正类型是TNotifyEvent,因此在触发事件时先要转成这种类型的过程指针后再进行调用
      method(Self);
    end;
end;
  定义了一个包含多处理事件的类后,再看看这种类如果在其客户类中被调用。如以下代码:
{类TClientClass中}
var
  myObj: TMyClass;
  //…
  myObj:= TMyClass.Create;
  myObj.OnSomeFired.Add(SomeFired1);
  myObj.OnSomeFired.Add(SomeFired2);
  当客户类代码中调用TMyClass的DoSth方法时,事件将被触发,而2个处理过程SomeFired1与SomeFired2则会依次调用,实现多处理的目的。

再发展一步
  上面的TEventObject类可以实现事件多处理的目的,但它对加入其中的过程指针类型没有检查,这是一个隐患。因此可以针对每一种事件要求的过程指针类型从TEventObject继承一个类,实现类型检查。如要求事件的类型是TNotifyEvent,就可以继承一个TNotifyEventObject类,如下面代码:
  TNotifyEventObject = class(TEventObject)
  public
    procedure Add(p: TNotifyEvent); overload;
    procedure Remove(p: TNotifyEvent); overload;
  end;
  以下是实现部分:
procedure TNotifyEventObject.Add(p: TNotifyEvent);
begin
  inherited Add(TMethod(p));
end;

procedure TNotifyEventObject.Remove(p: TNotifyEvent);
begin
  inherited Remove(TMethod(p));
end;
  在这个类中重载了添加与移除方法,可以有效地对过程指针类型进行检查。

  以上是我对Delphi 7中事件多处理问题的一个解决办法。如有兴趣,请光临我的博客http://allentao430.spaces.live.com赐教。

pi/4QPSK调制解调原理 文章目录1. π/4\pi/4π/4QPSK 信号的调制原理2. 匹配滤波器与成形滤波器 1. π/4\pi/4π/4QPSK 信号的调制原理 减小相位突变量的QPSK由偏置键控QPSK(OK-QPSK)和 π/4\pi/4π/4偏置的QPSK( π/4\pi/4π/4QPSK)。由于 π/4\pi/4π/4QPSK是用差分相位编码产生的(因此也叫做 π/4\pi/4π/4DQPSK),能有效地进行差分解调和鉴频器解调,在一些不易提取相干载波的场合很有用。 在常规的QPSK中,输入数据经过串/并变换后,分成 阅读详情

相关推荐

机场数据治理系列介绍(1):机场行业数据中台中的数据管理顶层设计方案

民航机场行业的数据中台中,有关数据管理顶层设计方案需要结合机场行业的业务特点和技术需求进行具体的设计,今日我们简要考量设计提供一个参考方案:

机场信息系统研究员的专栏 1578

delphi TMethod

program Test_Method; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type TExec = procedure of object; var _func: TMethod; Exec: TExec; procedure Test1; begin Writeln('Hell, word! This is a procedure.'); end; function Test2: Boolean; b.

sonadorje的专栏 1319

实现Windows高性能并发IOCP的DELPHI指南

简介:本文深入探讨了如何利用DELPHI语言实现基于Windows IO Completion Ports(IOCP)的高性能并发应用。IOCP作为Windows操作系统中的一种高效并发I/O技术,通过异步I/O模型显著提高了大量并发请求的处理性能。DELPHI提供的面向对象特性和与Windows API的紧密集成,使得使用IOCP变得更加便捷。

weixin_42181686的博客 500

Delphi中的匿名方法

在js的世界里,基本就是大量的“回调”和“异步”函数,剩下的就是按照顺序执行的javascript代码,所以总的来说,js中无“同步模型”。正是因为如此,javascript在运行时没有“多余的”线程,它们都在同一个“线程”中工作。任何第三方平台,凡是其API-Proxy代理服务器向你“代理转发(重定向)URL”,其响应结果,要么你在浏览器的导航器的地址栏中去取(Navigator.Location),要么你在响应头的redirect参数中去取,它们,都是异步的。Delphi及C++ Builder中,可以

pulledup的博客 1802

一个灵巧的Delphi多播实事件现方案.

已转至新博客 http://www.raysoftware.cn/?p=44 一个灵巧的Delphi多播实现方案.必须是支持泛型的Delphi版本.也就是Delphi2009以后.强烈建议用DelphiXE.   用法就是例如写一个Class指定一个Event,触发的时候会通知多个Method.和.NET的多播事件机制是一样的.   用法例如: type   TFakeButto

wr960204(武稀松)的专栏 4094

[转载] Delphi 7事件多处理机制

  首先解释一下这个题目。在我使用Delphi 7的过程中发现,一个对象的事件只能被一个过程处理。如果多次给这个对象的事件赋给处理事件的过程,最后真正处理事件的将是最后赋值的那个过程。例如,有类TMyClass中定义了一个事件OnSomeFired,在类TClientClass中该类被实例化,它的事件被处理。如下所示:constructor TClientClass.Create;var...

139

火鸟数据库 linux,firebird数据库

Firebird是一个跨平台的关系数据库系统,该系统使用起来十分方便、安全、可靠,操作和维护起来也是十分简单,且兼容性十分强大,目前能够运行在Windows、linux和各种Unix操作系统上,它既能作为多用户环境下的数据库服务器运行,也提供嵌入式数据库的实现。Firebird是什么?中文名为火鸟数据库是开源数据库,数据安全性比较好,费用也比较低,操作和维护就比较简单。如果需要卸载的话,双击安装程...

weixin_35705011的博客 2378

Firebird介绍

个人认为比较适合做桌面程序数据储存 以下是从网络获取: 1 含义  Firebird特性介绍firebird是一个全功能的,强大高效的,轻量级,免维护的数据库。它很容易让您从单用户,单数据库升级到企业级的应用。   一个firebird数据库服务器能够管理多个独立的数据库,每一个数据库同时可支持多个客户端连结。总之:它是一个开源的,强大在,可以自由使用的数据库(即使是商业上的使用)

生命在于折磨... 1007

Firebird特性介绍

<br />Firebird特性介绍:firebird是一个全功能的,强大高效的,轻量级,免维护的数据库。它很容易让您从单用户,单数据库升级到企业级的应用。<br /> 一个firebird数据库服务器能够管理多个独立的数据库,每一个数据库同时可支持多个客户端连结。总之:它是一个开源的,强大在,可以自由使用的数据库(即使是商业上的使用)<br /> 关键特性:<br /><br /> [separator]<br /><br /><br /> 支持原子性,并发性,隔离性等概念。<br /> MGA

paluo的专栏 850

firebird数据库介绍[转]

firebird数据库介绍 Firebird特性介绍:firebird是一个全功能的,强大高效的,轻量级,免维护的数据库。它很容易让您从单用户,单数据库升级到企业级的应用。 一个firebird数据库服务器能够管理多个独立的数据库,每一个数据库同时可支持多个客户端连结。总之:它是一个开源的,强大在,可以自由使用的数据库(即使是商业上的使用) 关键特性: 支持原子性,并...

deform0032的博客 274

Firebird 数据库使用心得

公司一个任务,需要一个免安装的嵌入式关系数据库,在试用了对比了 Access 和 Firebird 之后,选择了更简便、性能更好的后者。 Firebird 简介:       firebird是一个真正的关系数据库,支持存储过程、视图、触发器、事务等大型关系数据库的所有特性,它是一个开源的,可以自由使用的数据库(即使是商业上的使用)。具有以下的特点:   支持原子性,并发性

KaedaRukawa的专栏 2064

Firebird学习(01):Firebird数据库简介

概述 Firebird特性介绍:firebird是一个全功能的,强大高效的,轻量级,免维护的数据库。它很容易让您从单用户,单数据库升级到企业级的应用。  一个firebird数据库服务器能够管理多个独立的数据库,每一个数据库同时可支持多个客户端连结。总之:它是一个开源的,强大在,可以自由使用的数据库(即使是商业上的使用) 关键特性: 支持原子性,并发性,隔离性等

阿发的专栏 2590

用了下FIREBIRD,发现真的不错哦

Firebird特性介绍:firebird是一个全功能的,强大高效的,轻量级,免维护的数据库。它很容易让您从单用户,单数据库升级到企业级的应用。 一个firebird数据库服务器能够管理多个独立的数据库,每一个数据库同时可支持多个客户端连结。总之:它是一个开源的,强大在,可以自由使用的数据库(即使是商业上的使用) 关键特性: [separator] 支持原子性,并发性...

weixin_30532759的博客 139

关于Firebird数据库

关键特性:  支持原子性,并发性,隔离性等概念。  MGA:  支持事务的多个版本功能,  存储过程:  使用PSQL(Procedure SQL),你可以创建强大的存储过程来处理服务上的所有数据,你可以使用select Stored Procedure的形式,使用存储过程,以得到一个虚拟的表结构的结果。这样的话,你就可以很容易的在报表中使用它。  事件:  存储过程和

sonnydica的专栏 1054

Total-Text和ctw-1500数据集(带标签文件和图像).zip

Total-Text数据集概述:Total-Text是一个全面的场景文本检测与识别数据集,由香港中文大学的研究人员于2017年提出。它包含水平、多方向和曲形文本,旨在评估算法在复杂场景下的文本检测与识别能力。数据集详情:图片数量:Total-Text数据集包含1255张训练图片和300张测试图片。标注方式:文本使用四个点的坐标进行word级别的标注,形成封闭的文本框。数据来源:图片主要来源于谷歌街景,涵盖了多种自然场景下的文本。CTW-1500数据集概述:CTW-1500(Curved Text in the Wild)是一个专门用于曲形文本检测的数据集,由南京信息工程大学的研究人员于2017年提出。它旨在推动曲形文本检测技术的发展,提供丰富的曲形文本样本和精细的标注。数据集详情:图片数量:CTW-1500数据集包含1000张训练图片和500张测试图片。标注方式:文本使用14个边界点进行标注,形成封闭的弯曲文本框。这种标注方式能够更准确地描述曲形文本的形状。数据来源:图片同样来源于多种自然场景,包括街景、广告牌、商店招牌等。

上一篇: libhaur笔记1:Usage
下一篇: DELPHI 中如何提升进程令牌
iseekcode
博客等级 码龄18年 36粉丝 14原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值