想给一个动态创建的控件赋一个双击事件,因为还要传递一个参数进去,结果这样做却不行,望高手指点,怎么让我的代码通过.
代码如下:
procedure TForm1.View(var i:integer);
begin
showmessage('hi');
end;procedure TForm1.FormCreate(Sender: TObject);
var
PL:TPanel;
begin
PL:=TPanel.Create(Self);
PL.Parent:=Form1;
PL.OnDblClick:=View(1);
end;
代码如下:
procedure TForm1.View(var i:integer);
begin
showmessage('hi');
end;procedure TForm1.FormCreate(Sender: TObject);
var
PL:TPanel;
begin
PL:=TPanel.Create(Self);
PL.Parent:=Form1;
PL.OnDblClick:=View(1);
end;
procedure TForm1.view1(Sender: TObject);
begin
ShowMessage('1');
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Panel1.OnDblClick := view1;
end;如果真的要处理参数,可以将参数改成窗体的私有变量(在private下声明)
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure MyView(var i:integer);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.MyView(var i:integer);
begin
showmessage(intToStr(I));
end;var
I : integer;procedure TForm1.FormCreate(Sender: TObject);
var
PL:TPanel;
M : TMethod;
begin
PL:=TPanel.Create(Self);
PL.Parent:=self;
M.Code := TForm1.MethodAddress('MyView');
M.Data := @I;
PL.OnDblClick := TNotifyEvent(M);
end;
procedure MyPro2(Sender:TObject; i:integer);procedure TDlg_CosPowerRptA.MyEven(Sender: TObject);
begin //自定义事件
MyPro2(view1, i);
end;procedure TDlg_CosPowerRptA.MyPro2(Sender: TObject; i: integer);
begin //自定义过程
TView(sender).................
end;之后
PL.OnDblClick:=MyEven;另外,如果你指想传一个整数,可以把整数赋值给sender.tag.
procedure TForm1.Button1Click(Sender: TObject);
var
PL:TPanel;
begin
PL:=TPanel.Create(Self);
PL.Parent:=Form1;
PL.Caption:='A';
PL.Tag:=1;
PL.OnDblClick:=View;
end;procedure TForm1.View(sender: TObject);
begin
showmessage( TPanel(sender).Caption );
showmessage( IntToStr( TPanel(sender).Tag ) );
end;
还是你高,问题已解决
var
F : integer = 6688; //用一个变量试验procedure Proc( I : Integer);//别看是传Integer,实际上是传递变量的地址
begin
ShowMessage(IntToStr(PInteger(I)^));//所以要转换为地址把变量找出来
end;procedure TForm1.Button1Click(Sender: TObject);
var
PL : TPanel;
M : TMethod;
begin
PL := TPanel.Create(self);
PL.Parent := self;
PL.Caption := 'Panel''s Addr = ' + IntToStr(Integer(PL));
M.Code := @Proc;
M.Data := @F; // !! 传参就是用这个 Method.Data
PL.OnDblClick := TNotifyEvent(M);
end;
begin
ShowMessage(IntToStr(I^));
end;刚开始时的试验,还有一个导致不成功的很重要的原因,是用了类方法。
为什么procedure Proc( I : Integer);接收的参数是F:Integer的指针呢?
就因为Tmethod的Data指定了@F?
如果我传两个参数一个string ,一个integer
那么Proc( I :integer)接受的值也什么呢?
type
PMyInfo=^TInfo;
TInfo=packed record
i:integer;
s:string;
end;
procedure proc(i:Integer);
var p3:PMyInfo;
begin
p3:=PMyInfo(i);
showmessage('i:'+Inttostr(p3^.i)+'s:'+p3^.s);
end;procedure TForm1.Button1Click(Sender: TObject);
var panel:TPanel;
m:TMethod;
begin
panel:=TPanel.Create(Self);
panel.Parent:=self;
panel.Caption:='a';
m.Code:=@proc;
new(pp);
pp^.i:=1234;
pp^.s:='abcd';
m.Data:=pp;
panel.OnClick:=TNotifyEvent(M);
panel.Show;
end;
VV = record
I1,I2,I3 : integer;
end;var
F : VV; procedure Proc( I : PInteger);
begin
ShowMessage(IntToStr(I^));
ShowMessage(IntToStr(Pinteger(integer(I)+4)^));
ShowMessage(IntToStr(Pinteger(integer(I)+8)^));
end;procedure TForm1.Button1Click(Sender: TObject);
var
PL : TPanel;
M : TMethod;
begin
PL := TPanel.Create(self);
PL.Parent := self;
PL.Caption := 'Panel''s Addr = ' + IntToStr(Integer(PL));
M.Code := @Proc;
M.Data := @F;
PL.OnDblClick := TNotifyEvent(M);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
F.I1 := 8888;
F.I2 := 6666;
F.I3 := 9999;
end;指针偏移量,要看类型的长度了。关于“有什么意义”?我也不知道。
TStr = string[10];
VV = record
iField : integer;
sField : TStr;
dField : double;
end;
PStr = ^TStr;
var
F : VV;procedure Proc( I : Integer);
var P1 : PStr;
begin
ShowMessage(IntToStr(PInteger(I)^));
ShowMessage(PStr(integer(I)+4)^); //注意,记录的成员是顺序存放的,注意偏移量
ShowMessage(FloatToStr(PDouble(integer(I)+16)^));
end;procedure TForm1.Button1Click(Sender: TObject);
var
PL : TPanel;
M : TMethod;
begin
PL := TPanel.Create(self);
PL.Parent := self;
PL.Caption := 'Panel''s Addr = ' + IntToStr(Integer(PL));
M.Code := @Proc;
M.Data := @F;
PL.OnDblClick := TNotifyEvent(M);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
F.iField := 8888;
F.sField := 'abcdefghij';
F.dField := 12345.0876;
end;这个代码的意义还在于让我们深入理解OO。因为这个课题(TMethod)还可以深究下去的。
begin
ShowMessage(IntToStr((Sender as TControl).Tag));
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Panel1.Tag := 1;
Panel1.OnDblClick := @view1;
end;
Tag放结构地址。type
TDATAREC = record
d1: integer;
d2: integer;
end;
PDATAREC = ^TDATAREC;
procedure TForm1.view1(Sender: TObject);
begin
with Sender as TControl do
begin
ShowMessage(IntToStr(d1));
ShowMessage(IntToStr(d2));
end;
end;procedure TForm1.FormCreate(Sender: TObject);
var
prec:PDATAREC;
begin
New(prec);
prec.d1 := 10;
prec.d2 := 11;
Panel1.Tag := integer(prec);
Panel1.OnDblClick := @view1;
end;
TDATAREC = record
d1: integer;
d2: integer;
end;
PDATAREC = ^TDATAREC;
procedure TForm1.view1(Sender: TObject);
begin
with PDATAREC((Sender as TControl).Tag) do
begin
ShowMessage(IntToStr(d1));
ShowMessage(IntToStr(d2));
end;
end;procedure TForm1.FormCreate(Sender: TObject);
var
prec:PDATAREC;
begin
New(prec);
prec.d1 := 10;
prec.d2 := 11;
Panel1.Tag := integer(prec);
Panel1.OnDblClick := @view1;
end;
开头的 @还要去掉
改成
with PDATAREC((Sender as TControl).Tag)^ do
var
Panel : TPanel;
begin
Panel := TPanel.Create(Self);
Panel.Parent := Self;
Panel.Tag := i;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
View(1);
end;
begin
showmessage(InToStr(i));
end;procedure TForm1.FormCreate(Sender: TObject);
var
PL:TPanel;
begin
PL:=TPanel.Create(Self);
PL.Parent:=Form1;
PL.OnDblClick:=View(1);
end;
------------------------------------------
以上问题如果用Delphi2009的匿名方法就容易解决了:procedure TForm1.FormCreate(Sender: TObject);
var
PL:TPanel;
i: Integer;
begin
PL:=TPanel.Create(Self);
PL.Parent:=Form1;
i := 2;
PL.OnDblClick:=new NotifyEvent(sender: TObject)
begin
showmessage(IntToStr(i));
end;
end;强烈期待Delphi新功能。
同时要请您明确指出:我的哪些贴子的哪些回复中有问题,以致于您说“有些基础的概念并没有理的很清楚”,您指出了,可以便于我进一步提高。提前谢谢您了。3、您所说的“回到lz的问题上,其实还是第二种办法最适合”,在前面“失踪的月亮”和“强哥”各位已经说过了,并且我也已在向前几楼承认这是最合适的办法(我是这样回复月亮的:“是哈... 惭愧,撤!”),我觉得没有必要重复接受每一个人的声讨,向每一个人承认“错误”。4、对于您的代码,我不发表评论。
其实前面对lihuasoft兄有印象是在一个人问动态创建窗口释放出错的问题,看到这样一个问题您前前后后回了好几贴,使我都感到很感动,希望能帮忙说清楚问题。不要让兄台的好心浪费掉。但是感觉这种问题如果能比较系统的说明内存管理的方法,以及VCL结构中的特殊机制,让他避免以后出现这样的问题。比起解决当前的一个问题更好一点。特别是问问题的人处在轮着拿Application和Self做构造参数的“基于偶然编程”的状态。
刚刚专门回顾了一下这个帖子,发现其实lihuasoft兄并非没有提到基础概念,只是我当时只是大略看到几段代码轻忽过去了。所以应该说我前面说的有些基础概念没有理得很清楚的说法是不准确的,准确的说是我觉得lihuasoft兄要是更多强调基础概念会比直接写出代码会更有效一些,所以多嘴提出来希望这样能让您的热心更好的帮助到提问者。至于这个问题,我觉得lz不理解为什么自己的代码不能通过编译,问题是在于没有很好的掌握事件的概念。而不会是因为没有掌握TMethod。所以就算用TMethod的代码是完全正确的,个人认为对他也还是误导。后面列出个人的4个方法,并说第二种最适合,其实是想表示综合各种方案,解决这个问题还是这种很不完美的方式最现实,实在是Delphi的一个遗憾。并没有声讨您的方法不对,只有我说的对的意思。呵呵,对我的代码不发表评论。大概是里面有不严谨的地方吧。我先承认了,对比lihuasoft兄的认真,实在惭愧。因为手头没有Delphi,对于真正细节的问题真的是不敢参与,也就到这样的概念问题帖里掺和掺和了。如果有什么地方错的会造成误解的,还望指出,免得贻笑大方啊。最后还有个尾巴问题,TMethod结构确实仅仅是个Delphi实现细节,而且是不面向对象的。因为以当时的object pascal语言的特性如果完全面向对象方式来设计会相当的繁琐。所以采用了这个巧妙的折衷设计。这个问题我们可以继续讨论,不过觉得另开贴或者私下进行会更好一些。
就如你学习汽车驾驶,不可能一开始就讲汽车维修吧?会开就行,慢慢的你才能去修。