比如整个界面frmAA的Keypress控制录入edit框(edtCon)内容必须为数字.此函数已经控制好IsNum
procedure TfrmAAA.FormKeyPress(Sender: TObject; var Key: Char);
begin
方法一:
if (Not isNum(Key)) and (Sender as Tedit).name=edtCon.name then
key:=#13;
方法二:
if (Not isNum(Key)) and Tedit(Sender).name=edtCon.name then
key:=#13;
方法三:if (Not isNum(Key)) and activecontrol.name=edtCon.name then
key:=#13;
end;
结果:
方法一直接报错
方法二获取到Tedit(Sender).name的值为frmAA,即理解为KeyPress事件所在的控件,不合适
方法三正确,这里我们利用了窗体的ActiveControl属性,它代表当前获得焦点的输入文本框
另外,ComponentIndex属性代表了窗体控件放置的次序
///////////////////////////////////////
Sender举个例子
有两个button,共用一个onclick过程,当用户按下某个button时,sender就是用户按下的那个button,或者,这个过程并不是一个可触发事件的过程,只是一般过程,那么在其它地方调用这个过程的时候必需指定sender的名称,在这个过程里就可以引用这个名称了,sender一般为tobject,如果你知道这个sender应该是什么类的,在引用时加个强制类转换就行了,比如前面的button,你可以引用为tbutton(sender),这里你再按小数点就能提示出tbutton应该有的东西了
/////////////////////////////////////////
建立窗体是经常要用到他们如:
form1:=tform
.
create(application);
form1:=tform
.
create(self);
form1:=tform
.
create(
nil
);
form1:=tform
.
create(application); 当应用程序关闭时form1会被释放
form1:=tform
.
create(self); 当前窗体释放时form1会被释放
form1:=tform
.
create(
nil
); 需要自己动手释放,没人会为你代劳
Form1 := TForm
.
Create(Arg);
其中的Arg代表的是Form的Owner,也就是拥有者。
什么叫拥有者呢,意思就是说当这个拥有者释放的时候,Form1也会释放。
{************************************************************************************************************************}
在事件处理程序参数表中,至少含有一个参数Sender,它代表触发事件处理程序的构件,如在上例中,Sender就指Button2,有了Sender参数,可以使多个构件共用相同的事件处理程序,如下例:
Procedure
Tform1
.
Buttonclick(Sender:Tobject);
Begin
If
sender=button1
then
Label1
.
caption:=′看庭前花开花落 '
Else
Label2
.
caption:=′望天上云卷云舒′
End
;
在此例中,Button1,Button2共用了Buttonclick事件处理程序。
Self是指所编的程序范围是在哪一个类中,Delphi中大都在窗体范围内编程,因此,self即指窗体,如果在编写一个类或是一个组件,则 self指该类或组件。我们在函数或过程的声明中可看出self是代表哪个组件,即self代表‘.’号之前的组件,如在第一个例子中,self代表 Tform1。另外应注意,self只能用在类方法中,而不能用在过程或函数中,如下例用法是错的:
Function
a1(B:
Integer
):
Integer
;
Begin
……
Button:=tbutton
.
create(self);……
End
;
三、Clientheight和Height,Clientwidth和Width的区别:
对于一般的构件而言,Height就是Clientheight,Width就是Clientwidth,而对于窗体而言,Height是包括标题条 在内的高度,而Clientheight是指窗体工作区的高度。同理,Clientwidth是指定窗体工作区的宽度。
从上面陈述可知,理解Ower和Parent,Self和Sender,Clientheight和Height,Clientwidth和Width区别,对于Delphi中正确编程是重要的。
无意中上网在csdn论坛看到了一个很形象的解释:可以参考一下
方法,事件,sender,Tobject,self
你是一个人类(Tobject),你有你自己的性别,年龄,身高等(属性),你也会攀爬蹬走(方法),你也有你的情绪,思想,当别人说你好的时候你很高 兴,说你坏时你会很沮丧(事件),有一天你自己(self)听到别人(sender)说你的女朋友好漂亮传给你的思想(事件),这时你会非常不高兴(事件 处理外界的响应)
{*************************************************************************************************************************}
在事件处理程序参数表中,至少含有一个参数Sender,它代表触发事件处理程序的构件,如在上例中,Sender就指Button2,有了Sender参数,可以使多个构件共用相同的事件处理程序,如下例:
Procedure
Tform1
.
Buttonclick(Sender:Tobject);
Begin
If
sender=button1
then
Label1
.
caption:=′看庭前花开花落'
Else
Label2
.
caption:=′望天上云卷云舒′
End
;
在此例中,Button1,Button2共用了Buttonclick事件处理程序。
Self是指所编的程序范围是在哪一个类中,Delphi中大都在窗体范围内编程,因此,self即指窗体,如果在编写一个类或是一个组件,则self 指该类或组件。我们在函数或过程的声明中可看出self是代表哪个组件,即self代表‘.’号之前的组件,如在第一个例子中,self代表 Tform1。另外应注意,self只能用在类方法中,而不能用在过程或函数中,如下例用法是错的:
Function
a1(B:
Integer
):
Integer
;
Begin
……
Button:=tbutton
.
create(self);……
End
;
Clientheight和Height,Clientwidth和Width的区别:
对于一般的构件而言,Height就是Clientheight,Width就是Clientwidth,而对于窗体而言,Height是包括标题条在内的高度,而Clientheight是指窗体工作区的高度。同理,Clientwidth是指定窗体工作区的宽度。
从上面陈述可知,理解Ower和Parent,Self和Sender,Clientheight和Height,Clientwidth和Width区别,对于Delphi中正确编程是重要的。
Delphi 中Sender对象的定义!
1.
Sender的定义:
每一个事件处理里面至少都有一个Sender参数。比如:
procedure
TForm1
.
Button1Click(Sender:TObject);
begin
...
end
;
Sender的含义就是代表调用TForm1
.
Button1Click这个过程的控件. 由于Sender是TObject,所以任何
object
都可以赋给Sender.
当你点击BUTTON1时,会产生一个Button1Click事件,系统会把Button1传递给Button1Click过程坐为参数,也就是所说的Sender.
2.
Sender的用法:
<
1
>.由于Sender代表了调用所在过程的控件,那么你就可以直接把它拿来当那个控件用,不过如果要用属性的话,最好写成(Sender
as
控件名).控件属性:=... 例如:
procedure
TForm1
.
Edit1Click(Sender: TObject);
begin
with
Sender
as
TEdit
do
begin
text:=’hello’;
end
;
end
;
<
2
>.如果在两个事件中处理同样的事情,那么可以利用Sender来省去重写同样的过程。例如:
var
SearchOptions: TLocateOptions;
searchword:
String
;
begin
if
sender = Editid
then
begin
searchword:=
'Empid'
;
EditCardnum
.
text :=
''
;
end
else
if
sender= EditCardnum
then
Begin
searchword:=
'Cardnum'
;
Editid
.
text:=
''
;
end
;
SearchOptions := [loPartialKey];
tabPV_Card
.
Locate(searchword, TEdit(sender).Text , SearchOptions);
//Editid,EditCardnum两个TEdit事件处理同样的事, tabPV_Card為Ttable控件
end
;
|
///////////////////////////////////////////////////////
Sender是一个TObject类型的参数,它告诉Delphi哪个控件接收这个事件并调用相应的处理过程。你可以编写一个单一的事件处理句柄,通过Sender参数和IF…THEN…语句或者CASE语句配合,来处理多个构件。发生事件的构件或控件的值已经赋给了Sender参数,该参数的用途之一就在于:可以使用保留字IS来测试Sender,以便找到调用这个事件处理句柄的构件或控件的类型。例如,将表单中编辑框和标签的Click事件的处理句柄都指向表单的xxx过程,编辑框和标签对Click事件有不同的反应:
procedure TForm1xxx(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参数的用法,特别是在事件处理中的角色。Sender参数代表触发事件的控件对象,可用于判断控件类型并进行相应操作。通过Sender结合IS和AS操作符,可以实现对不同控件的统一事件处理,体现了Delphi的面向对象重用性。
941

被折叠的 条评论
为什么被折叠?



