Sender是一个TObject类型的参数,它告诉Delphi哪个控件接收这个事件并调用相应的处理过程。你可以编写一个单一的事件处理句柄,通过Sender参数和IF…THEN…语句或者CASE语句配合,来处理多个构件。发生事件的构件或控件的值已经赋给了Sender参数,该参数的用途之一就在于:可以使用保留字IS来测试Sender,以便找到调用这个事件处理句柄的构件或控件的类型。例如,将表单中编辑框和标签的Click事件的处理句柄都指向表单的xxx过程,编辑框和标签对Click事件有不同的反应:
  procedure TForm1xxx(Sender:TObject);
  begin
  if(sender is Tedit) then
  showmessage(′this is a editbox′);
  if(sender is Tlabel) then
  showmessage(′this is a label′);
  end;
  Sender参数的第二个用途是结合AS操作符进行类型转换,将若干个派生于某一父类的子类强制转换成该父类。例如表单中有一个TEdit类控件和一个TMemo控件,它们实际上都派生于TcustomEdit类,如果你要为二者的某一事件提供同样处理,可以将二者事件句柄都指向自定义的过程yyy:
  Procedure TForm1.yyy(Sender:TObject);
  begin
  (sender as TcustomEdit).text:=′This is some demo text′;
  end;
  在过程中,AS操作符将TEdit类和TMemo类均强制转换成TcustomEdit类,再对TcustomEdit类的属性赋值。注意这种转换必须符合Delphi中类的层次关系。
  使用Sender参数可以通过单一过程段处理多类控件,真正体现了Delphi面向对象的重用性。

-----------------------
Delphi之Sender

Sender其实就是函数的一个参数,你看看VCL中触发事件的代码,就会发现Sender往往代表了 “事件的触发者”,或者说“这个外挂的事件处理函数的调用者”,目的是为了让事件处理函数有一个参考尤其是当一个事件处理函数挂接到多个实例时。

//看个例子
procedure THappy.MakeLove;
var
bCancel :Boolean;
bNeedBath :Boolean;
bHappy :Boolean;
begin
bCancel := False;
bNeedBath := True;

if assigned(FOnBeforeMakeLove) then
FOnBeforeMakeLove(Self, bNeedBath, bCancel);

if bCancel then Exit;
if bNeedBath then GotoBath;

bHappy := DoMakeLove(Self.Boy, Self.Girl);

if assigned(FOnAfterMakeLove) then
FOnAfterMakeLove(Self, bHappy);
end;

procedure XXXBeforeMakeLove(Sender :TObject; var ANeedBath, ACancel :Boolean);
begin
if Sender is THappy then begin
if (THappy(Sender).Boy <> me) or (THappy(Sender).Girl.Age < 16)
or (THappy(Sender).Girl.Age > 25) then
begin
ACancel := True;
end;
ANeedBath := OfCourseTrue;
end;
end;

procedure XXXAfterMakeLove(Sender :TObject; const AHappy :Boolean);
begin
if AHappy then
begin
ShowMessage('爽歪歪...');
end
else begin
ShowMessage('555...');
end;
end;

-------

这个东西感觉还是比较抽象的。需要慢慢的细细体会。
从理论上讲Sender是一个四个字节的指针变量,里面存放的指针内容是(堆)栈中对象实体的首字节地址。我们在每次在设计APP的时候,会在Object Inspector里面双击事件属性来建立我们需要的代码,以完成预期的功能。当我们进行双击的时候,Delphi的IDE(Integreted Development Environment)会为我们自动建立与事件属性对应的过程,例如,当我们双击Form1变量的OnClick属性时,IDE会自动在TForm1类 的初始化部分创建如下的代码:
procedure TForm1.Form1Click(Sender:TObject);
同时在实现部分创建上述过程的框架,如下:
procedure TForm1.Form1Click(Sender:TObject);
begin
//初始情况下,这里并没有任何代码!
end;
然后我们在程序中可以调用这个建立好的方法,例如我们在窗体上的Button1的OnClick方法中执行如下代码:
...
Self.Form1Click(Button1);
...
同时,我们假设在Form1Click中代码如下:
...
if Sender=Button1 then
ShowMessage(TButton(Sender).Caption); //这里在判断条件为真的情况下使用强制转换
...
可以看到在代用Form1Click时,为其传递的Sender参数可以自己定义,因此严格来讲Sender参数并不代表真正触发此事件对应方法的对象,确切的说应该是用户指定的触发此事件对应方法的对象!

Sender表示触发当前事件代码的对象,而Self才表示当前方法指针指向的方法所属的对象
例如对于TForm的对象Form1,起OnClick事件中包含参数Sender,如下

procedure TForm1.FormClick(Sender:TObject);
这里的FormClick实际是Delphi的IDE在设计期为你在窗口类的初始化未命名部分自动建立的方法,但他的可见性是Pulished的,因此具有RTTI信息!!!!

在运行期间,当前的方法指针FClick指向的方法属性(即事件)OnClick所属于的对象为TForm1的实例Form1,因此Self代表的就是对 象Form1,而触发这个事件的对象不一定是Form1,有可能是Button1,所以Sender需要进行判断。你可以在Button1的 OnClick事件中调用如下代码:
Form1.OnClick(Button1);
这个时候在Form1的OnClick事件中对Sender进行判断就是Button1,而不是Form1了!

需要注意的是,由于Sender的类型为TObject,因此实际使用的时候最好进行类型转换!!!!使用As运算符!!!!

Delphi中Sender对象的知识的更多相关文章

  1. 关于delphi 中 Sender的学习

    sender是 事件的触发者,我发现所有的组件的事件 基本上都是 传Sender. 示例效果图: 代码: 接着来,既然TButton是个类,且publish哪里有事件,我们也可以看看这个事件的原型.

  2. delphi 中判断对象是否具备某一属性

    Uses   TypInfo;         {$R   *.dfm}         procedure   TForm1.Button1Click(Sender:   TObject);     ...

  3. Delphi中的Sender:TObject对象解析

    Delphi中的Sender:TObject对象解析 procedure TForm1.Button1Click(Sender: TObject); begin end; 解析:Procedure是过 ...

  4. Delphi中的Sender:TObject对象解析转载

    https://blog.csdn.net/jl_tiny/article/details/24376661 Delphi中的Sender:TObject对象解析 procedure TForm1.B ...

  5. 关于 Delphi 中的Sender和易混淆的概念(转)

    /////////////////////////////////////////////////////// Delphi 中Sender对象的定义///////////////////////// ...

  6. Delphi中使用比较少的一些语法

    本文是为了加强记忆而写,这里写的大多数内容都是在编程的日常工作中使用频率不高的东西,但是又十分重要. ---Murphy 1,构造和析构函数: a,构造函数: 一般基于TComponent组件的派生类 ...

  7. 转:Delphi中使用比较少的一些语法

    http://www.cnblogs.com/Murphieston/p/5577836.html 本文是为了加强记忆而写,这里写的大多数内容都是在编程的日常工作中使用频率不高的东西,但是又十分重要. ...

  8. Delphi引用C对象文件

    C语言应用非常广泛,并在世界各地拥有大量的代码库.这些代码库与Delphi的可比性较小,因此如果我们无需转换为Delphi代码而可以直接使用这些库的部分代码就完美了.幸运的是,Delphi允许连接到C ...

  9. Delphi引用C对象文件(转)

    源:http://blog.csdn.net/henreash/article/details/7357618 C语言应用非常广泛,并在世界各地拥有大量的代码库.这些代码库与Delphi的可比性较小, ...

随机推荐

  1. Lambda实战(多练习)

    import org.junit.Test; import java.math.BigDecimal; import java.time.LocalDate; import java.util.*; ...

  2. golang使用rabbitMQ入门代码

    package main import ( "github.com/streadway/amqp" "log" "time" ) func ...

  3. 04IP编址(网络层)

    帧中type为0x0800,送给ip   ip报文结构 TTL 生存时间最大为255,经过三层设备就减1 protocol:协议号 version:4,6 source ip address:源ip编 ...

  4. mySQL安装的时候一直卡在starting server这里解决办法

    昨天安装mySQL的时候一直卡在了starting server这里,等了半天都没反应,后来就去网上寻找解决办法,大部分是说什么设置mysql本地启动服务啊,删除注册表啊,这些办法都试过了 然并卵. ...

  5. 20145234黄斐《信息安全系统设计基础》第六周学习总结(Y86模拟器的安装)

    Y86模拟器的安装 由于本人的电脑有些问题,在安装的时候忽然断电导致之前的成果都没有截图. 1.安装bison和flex词法分析工具 sudo apt-get install bison flex t ...

  6. 成都Uber优步司机奖励政策(3月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. quartz与Spring整合

    1.创建maven工程,导入spring和quartz相关依赖 2.创建任务类 3.在spring配置文件中配置任务类 4.在spring配置文件中配置JobDetail 5.在spring配置文件中 ...

  8. 阿里otter使用问题汇总

    最近在使用otter做为和表从库.(100个分表太难查询了) user_00,user_01...user_99 => user_all 1.问题DDL语句不能执行(exception:setl ...

  9. 第一模块·开发基础-第1章 Python基础语法

    Python开发工具课前预习 01 Python全栈开发课程介绍1 02 Python全栈开发课程介绍2 03 Python全栈开发课程介绍3 04 编程语言介绍(一) 05 编程语言介绍(二)机器语 ...

  10. Python简要标准库(1)

    sys sys这个模块让你能够访问与Python解释器联系紧密的变量和函数 其中的一些在下表 F argv 命令行参数,包括脚本名称 exit([arg]) 退出当前的程序,可选参数为给定的返回值或者 ...