跪求3年解不开的难题:某非空事件,动态增加动作后实现新旧2个动作 (如Button的onClick为显示’OK‘, 动态加入显示’Bye‘字串,点击button

  • 主题发起人 主题发起人 june_8824086
  • 开始时间 开始时间
J

june_8824086

Unregistered / Unconfirmed
GUEST, unregistred user!
跪求3年解不开的难题:某非空事件,动态增加动作后实现新旧2个动作 (如Button的onClick为显示’OK‘, 动态加入显示’Bye‘字串,点击button即显示’ok‘也显示’Bye‘)。(300)<br />困扰了几年的一个问题。 某一事件已指定动作, 运行时需要此事件再多做1个动作。但此时是动态指定。即对该事件重新定义。要求既执行本身已有的动作,又执行新指定的动作正常形式: 某窗体有N个Button。每个Button各司其职。我想在每个Button点击时改变状态为disenable,以标识此Button已经执行过。(假如有此业务) 可能的代码 for I := to Componets.count - 1 do if Components is TButton then if not assgined(TButton(Components).onClick) then TButton(Components).onClick := 某定义Click else TButton(Components).onClick := (本身Click + 某定义Click)// 实现方法??? 最简形式:主窗体上只有一个Button, onClick事件默认执行showmessage('ok');,想动态设定该Button在点击时除了执行原有功能即显示"OK"外,再显示”Bye"。(显示顺序无要求) 简单代码,加强表述:unit Unit1;interfaceuses Forms, Dialogs, Controls, Classes, StdCtrls;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); public procedure btnClick(Sender: TObject); end;var Form1: TForm1;implementationprocedure TForm1.btnClick(Sender: TObject);begin ShowMessage('Bye');end;procedure TForm1.Button1Click(Sender: TObject);begin ShowMessage('OK');end;procedure TForm1.FormCreate(Sender: TObject);begin// 期望集成前后两个功能// Button1.OnClick := Button1.OnClick + btnClick; // Button1.OnClick := ? // 求实现方法end;end.
 
1.在新事件处理中调用旧事件处理程序2.再写一个新的事件处理程序,分别调用两个以前的程序
 
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Button1: TButton; btn: TButton; procedure btnClick(Sender: TObject); procedure Button1Click(Sender: TObject); procedure ButtonClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}procedure TForm1.btnClick(Sender: TObject);begin ShowMessage('Bye');end;procedure TForm1.Button1Click(Sender: TObject);begin ShowMessage('OK');end;procedure TForm1.ButtonClick(Sender: TObject);begin btnClick(Sender); Button1Click(Sender);end;procedure TForm1.FormCreate(Sender: TObject);begin Button1.OnClick := ButtonClick;end;end.
 
关键是怎么样调用。我也试过类似方法,因为动态取原事件时原因。不小心就嵌套溢出了。 能不能给出具体的核心代码procedure TForm1.btnClick(Sender: TObject);begin TButton(Sender).Click; //加标志位等,诸如此类的代码好象都不行, ShowMessage('Bye');end;
 
按我上面的方法,你试试,我测试了,可行。
 
谢谢 kaida, 你说的很正确, 是我没有说明白,但我会给分的。在正常的业务环境中,原有的 Button1Click(Sender);很有可能无法确定。 而只能用 TButoon(Sender)的方式得到原有控件。 比如 某窗体有N个Button。每个Button各司其职。我想在每个Button点击时改变状态为disenable,以标识此Button已经执行过。 可能的代码 for I := to Componets.count - 1 do if Components is TButton then if not assgined(TButton(Components).onClick) then TButton(Components).onClick := 某定义Click else TButton(Components).onClick := 某定义Click + 实现方法??? 请kaida兄及所有高手继续施以援手。不胜感谢!!!!
 
好像命题表达的不是很清楚,没弄明白楼主究竟想要实现的效果。。。
 
procedure TForm1.ButtonClickEx(Sender:TObject);var ev:TNotifyEvent; pm:^Method;begin pm:=^Method(TComponent(Sender).Tag); if pm<>nil then begin TMethod(ev).Code:=pm.Code; TMethod(ev).Data:=pm.Data; ev(Sender); end; //添加新动作。end; var ev:TNotifyEvent; pm:^TMethod;for I := to Componets.count - 1 do if Components is TButton then begin if TButton(Components).onClick<>nil then begin ev:=TButton(Components).onClick; New(pm); pm.Code:=TMethod(ev).Code; pm.Data:=TMethod(ev).Data; Components.Tag:=Integer(pm); end else Components.Tag:=0; TButton(Components).onClick := ButtonClickEx end; 为每个Button分配的一个TMethod结构的释放请自己实现。
 
为什么非要这样,加一个判断不就可实现业务了吗
 
楼上说得太专业。能否说得通俗一点?
 
个人觉得合理的解决方案是增加一个代理类,负责转发事件即可。比如Button.Click->调用代理类的某个方法->消息转发,通知其他步骤。这样一来,楼主核心的两个问题得以解决,第一要求多事件,转发即可;第二要求事件标识,如果已经接收过消息或者说执行过事件,则不再进行转发,具体实现在代理里面加个标识就搞定。另外,由于事件是动态绑定的,个人认为利用回调技术可能效果会好一点。
 
回调技术?VCL的事件属性就是回调了
 
关键是你要保存这个Button原有的事件处理函数,然后用自己的去取代它。自己的处理函数中按需要调用原来保存的处理函数。
 
地质灾害的水平很好!不过我不推荐这样用,还是声明一个代理结构比较合理,容易理解。比如最简单的TMyEvent=record Event:TNotifyEvent;end;生成的内存结构和TMethod一样的 但是具有类型,用着还方便。然后每个onclick里面都是处理一个Array of TmyEvent这样的一个动态数组就行了(Tlist也可以),添加事件就多添加一个数组的元素,象dinglj1760说的写成一个代理类就更好了,添加几个方法的不是。C#中的事件就具有这个功能了。
 
不知道我这样理解你的需求是不是对的,以下还是你的代码,简单修改了一下unit Unit1;interfaceuses Forms, Dialogs, Controls, Classes, StdCtrls;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); public procedure btnClick(Sender: TObject); end;var Form1: TForm1;implementationprocedure TForm1.btnClick(Sender: TObject);begin //ShowMessage('OK'); 这句要不要我也不清楚你的需求,要就打开吧! ShowMessage('Bye');end;procedure TForm1.Button1Click(Sender: TObject);begin ShowMessage('OK'); Button1.OnClick = btnClick;end;procedure TForm1.FormCreate(Sender: TObject);begin// 期望集成前后两个功能// Button1.OnClick := Button1.OnClick + btnClick; // Button1.OnClick := ? // 求实现方法end;end.
 
// 这样就可以了unit Unit1;interfaceuses Forms, Dialogs, Controls, Classes, StdCtrls;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private FOldClick: TNotifyEvent; // 记录老的事件 public procedure btnClick(Sender: TObject); end;var Form1: TForm1;implementationprocedure TForm1.btnClick(Sender: TObject);begin // 执行老的 if Assinged(FOldClick) then FOldClick(Sender); // 执行新的 ShowMessage('Bye');end;procedure TForm1.Button1Click(Sender: TObject);begin ShowMessage('OK');end;procedure TForm1.FormCreate(Sender: TObject);begin // 期望集成前后两个功能// Button1.OnClick := Button1.OnClick + btnClick; // Button1.OnClick := ? // 求实现方法 FOldClick := nil; if Assigned(Button1.OnClick) then begin // 记录老的 FOldClick := Button1.OnClick; // 转接新的 Button1.OnClick := btnClick; end; end;end.
 
谢谢大家,地质兄的思路给了最大启示。 只要设置全局变量 ev:TnotifyEvent就可以了 在 cteate时 给每一个控件的onclick赋值即可 for i = 0 to componentscount - 1 do ev := tbutton(compoents).onlick; tbutton(compoents).onclick := clickevent; porcedure clicevent(sender: tobject); begin ev(sender); tbutton(sender).disabled := false // 或执行其它增加的动作。 end;谢谢大家了。大家都有分。一起发财,呵可呵。。。。。。。。。
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
732
import
I
I
回复
0
查看
611
import
I
后退
顶部