Events (Delphi)Delphi中事件

本文介绍Delphi中的事件处理机制,包括事件属性、事件处理方法及如何触发多个事件处理方法。通过示例展示如何定义和使用事件,以及如何在一个事件中调用多个事件处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Events (Delphi)

This topic describes the following material:

  • Event properties and event handlers (事件属性和时间处理方法)
  • Triggering multiple event handlers(触发多个事件处理方法)

About Events(关于事件)

An event links an occurrence in the system with the code that responds to that occurrence. The occurrence triggers the execution of a procedure called an event handler. The event handler performs the tasks that are required in response to the occurrence. Events allow the behavior of a component to be customized at design-time or at run time. To change the behavior of the component, replace the event handler with a custom event handler that will have the desired behavior.


一个事件链接系统中一个事件发生和对这个事件放生响应代码。当事件发生时被触发执行的过程被称作事件处理方法。事件处理方法执行一个要求响应事件发生的任务,如果要实现期望的行为,那么需要使用自定义的事件处理方法替换原来的事件处理方法。

Event Properties and Event Handlers(事件属性和事件处理方法)

Components that are written in Delphi use properties to indicate the event handler that will be executed when the event occurs. By convention, the name of an event property begins with "On", and the property is implemented with a field rather than read/write methods. The value stored by the property is a method pointer, pointing to the event handler procedure.

在 Delphi的组件中,用属性表示事件处理方法,这些方法在事件发生的时候将会被执行。通常上,事件属性的名字是以On开头的,事件属性是使用字段实现,而不是使用read/write方法的方式。储存在属性中的值是方法的指针,指向事件处理方法的过程。


In the following example, the TObservedObject class includes an OnPing event, of type TPingEvent. The FOnPing field is used to store the event handler. The event handler in this example, TListener.Ping, prints 'TListener has been pinged!'.

 program EventDemo;
 
 {$APPTYPE CONSOLE}
 type
   { Define a procedural type }
   TPingEvent = procedure of object;
 
   { The observed object }
   TObservedObject = class
   private
     FPing: TPingEvent;
 
   public
     property OnPing: TPingEvent read FPing write FPing;
 
     { Triggers the event if anything is registered }
     procedure TriggerEvent();
   end;
 
   { The listener }
   TListener = class
     procedure Ping;
   end;
 
 
 procedure TObservedObject.TriggerEvent;
 begin
   { Call the registerd event only if there is a listener }
   if Assigned(FPing) then
     FPing();
 end;
 
 procedure TListener.Ping;
 begin
   Writeln('TListener has been pinged.');
 end;
 
 var
   ObservedObject: TObservedObject;
   Listener: TListener;
 
 begin
   { Create object instances }
   ObservedObject := TObservedObject.Create();
   Listener := TListener.Create();
 
   { Register the event handler }
   ObservedObject.OnPing := Listener.Ping;
 
   { Trigger the event }
   ObservedObject.TriggerEvent();//Should output 'TListener has been pinged'
   Readln;                       // Pause console before closing
 end.

Triggering Multiple Event Handlers(触发多事件处理方法)

In Delphi, events can be assigned only a single event handler. If multiple event handlers must be executed in response to an event, the event handler assigned to the event must call any other event handlers. 

在Delphi中,事件仅能被赋值一个事件处理方法(这个和.net是不同的,.net事件天生带有多播特性(multicast)),如果响应一个事件必须执行多个事件处理方法的话,那么赋值给事件的事件处理方法必须要调用所有其他的事件处理方法。

In the following code, a subclass of TListener called TListenerSubclass has its own event handler called Ping2. In this example, the Ping2 event handler must explicitly call the TListener.Ping event handler in order to trigger it in response to the OnPing event:

 program EventDemo2;
 
 {$APPTYPE CONSOLE}
 
 type
   { Define a procedural type }
   TPingEvent = procedure of object;
 
   { The observed object }
   TObservedObject = class
   private
     FPing: TPingEvent;
 
   public
     property OnPing: TPingEvent read FPing write FPing;
 
     { Triggers the event if anything is registered }
     procedure TriggerEvent();
   end;
 
   { The listener }
   TListener = class
     procedure Ping;
   end;
 
   { The listener sub-class }
   TListenerSubclass = class(TListener)
     procedure Ping2;
   end;
 
 procedure TObservedObject.TriggerEvent;
 begin
   { Call the registerd event only if there is a listener }
   if Assigned(FPing) then
     FPing();
 end;
 
 procedure TListener.Ping;
 begin
   Writeln('TListener has been pinged.');
 end;
 
 procedure TListenerSubclass.Ping2;
 begin
   { Call the base class ping }
   Self.Ping();
   Writeln('TListenerSubclass has been pinged.');
 end;
 
 var
   ObservedObject: TObservedObject;
   Listener: TListenerSubclass;
 
 begin
   { Create object instances }
   ObservedObject := TObservedObject.Create();
   Listener := TListenerSubclass.Create();
 
   { Register the event handler }
   ObservedObject.OnPing := Listener.Ping2;
 
   { Trigger the event }
   ObservedObject.TriggerEvent();//Should output 'TListener has been pinged'
                              //and then 'TListenerSubclass has been pinged'
   Readln;                    // Pause console before closing
 end.

### 设备驱动模型的概念 设备驱动模型是一种用于管理硬件资源的操作系统机制,它通过抽象层将操作系统与底层硬件隔离开来。这种设计使得开发者可以更方便地编写适用于不同硬件平台的软件[^1]。 在 Linux 内核中,设备驱动模型的核心组件包括 kobject 子系统、总线、设备和驱动程序以及 Sysfs 文件系统。这些组成部分共同构建了一个统一的框架,使设备管理和配置变得更加高效和灵活。 Zephyr 是一种实时嵌入式操作系统 (RTOS),其驱动模型也遵循类似的结构化方法。该模型主要由五个基本元素构成:设备对象、驱动接口函数集合、初始化回调函数指针表、运行状态标志位组以及其他辅助数据成员。通过对这五部分的设计实现,能够完成特定功能模块的支持工作[^2]。 ### 实现方式 #### 1. **Linux 的设备驱动模型** - **Kobject 子系统**: Kobject 提供了一种通用的数据结构用来表示内核中的各种实体(如设备)。每一个 kobject 都会关联到 sysfs 中的一个目录节点,并允许用户空间访问控制相应的属性值。 - **总线、设备和驱动模型**: 总线代表连接多个物理或者逻辑装置之间的通信路径;而每台机器上的实际外设则被建模成一个个独立的对象——即 “device”。与此同时,“driver” 则定义了如何操作某个类型的 device 所需的一系列 API 接口描述符列表。 - **Sysfs 系统**: 它是一个基于内存的文件系统,提供了关于当前加载的所有 drivers 和 devices 的信息视图给应用程序查询使用。 #### 2. **Zephyr 的设备驱动模型** Zephyr RTOS 对于每一类具体的 peripheral 控制器都给出了标准化的 include 头档名下可供调用的标准服务命令集。当开发人员想要利用某款芯片内部集成的功能单元时,只需参照官方文档说明去实例化对应的 handler 即可快速上手应用层面编程。 另外,在实现阶段还需要特别注意针对上述提到过的那几个核心要素逐一落实细节处理方案: - 创建并注册新的 devicetree 节点; - 编写适配目标 SoC 架构特性的 probe 函数体代码片段; - 设置好 power management policy 参数选项等等。 ```c // 示例 C 语言代码展示简单的 GPIO 初始化过程 #include <zephyr/drivers/gpio.h> const struct device *dev; int ret; dev = device_get_binding(DT_LABEL(GPIO_PORT)); if (!dev) { printk("Error: failed to get %s\n", DT_LABEL(GPIO_PORT)); } ret = gpio_pin_configure(dev, PIN_NUMBER, GPIO_OUTPUT_ACTIVE); if (ret != 0) { printk("Error configuring pin %d (%d)\n", PIN_NUMBER, ret); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值