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. BZOJ1821_Group部落划分_KEY

    题目传送门 这是一道并查集的题目,相信很多人都看出来了. 用一个类似Kurskal的东西求出最近的最大值. 对于一些可以划分在同一个部落里的边,我们一定是优先选择短边合并. code: /****** ...

  2. 北京Uber优步司机奖励政策(3月12日~3月13日)

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

  3. LeetCode: 53. Maximum Subarray(Easy)

    1. 原题链接 https://leetcode.com/problems/maximum-subarray/discuss/ 2. 题目要求 给定一个整型数组,返回其子串之和的最大值 例如,[-2, ...

  4. Android远程推送笔记

    Android远程推送笔记 Android推送有很多种实现方案,但都没办法和苹果的APNS比拟,这里主要来讲述一下我遇到的问题,和作出的抉择. 首先,为了快速接入,所以就没有自己搭建推送服务器,而是使 ...

  5. 一文带你了解 Raft 一致性协议的关键点

    此文已由作者孙建良授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Raft 协议的发布,对分布式行业是一大福音,虽然在核心协议上基本都是师继 Paxos 祖师爷(lampor ...

  6. Odd CSS syntax. [class^='icon-'], [class*=' icon-']

    原文: https://stackoverflow.com/questions/20322740/odd-css-syntax-class-icon-class-icon I am going thr ...

  7. php随机类型验证码

    开发使用验证码的意义就是为了区别操作者是人还是机器,防止自动脚本对服务器造成灾难性的攻击 目前有各种各样的验证码种类,譬如:静态字符验证码.算术验证码.拖拽验证码.识别文字或识别物品验证码(高级),下 ...

  8. 贵州省未来二十年的投资机会的探讨2>

    房产投资 升值最快的 在教育资源丰富  生活方便的 地方 价格和地段取其中之一. 其次 车位 再其次墓地等 公寓住房. 还有商标 和网站注册 公司注册 除了以上的这些  还有茅台生效酒 收藏

  9. MySQL Proxy使用

    使用MySQL将读写请求转接到主从Server. 一 安装MySQL Proxy MySQL Proxy的二进制版非常方便,下载解压缩后即用. 解压缩的目录为: $mysql-proxy_instal ...

  10. POJ 1739 Tony's Tour(插头DP)

    Description A square township has been divided up into n*m(n rows and m columns) square plots (1< ...