線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2133
推到 Plurk!
推到 Facebook!

onExit 事件是否能(在父系的form下指令)暫時取消之後再加回來

答題得分者是:jow
shininggod
一般會員


發表:16
回覆:20
積分:17
註冊:2009-05-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-02-25 19:44:14 IP:114.32.xxx.xxx 未訂閱
我想的到的方案是用一個全預變數來判斷要不要跑 onExit, 可是這樣要每個onexit都要另外寫orz...

例如一個TDBedit:
現在是說,因為使用者在查資料的時候要copy上面的字,所以不能給他 enable := false 鎖住
問題是他copy 完滑鼠一點別的就會觸發 onexit,

但是他在加/改資料的時候 onexit 又要能跑好判斷資料是不是可接受的形式.

在知道procedure 名稱的時候是可以用
查詢時
TDbMyEdit.OnExit := nil;

新增/修改
TDbMyEdit.OnExit := TDbMyEditonExit;

這樣加的回來

可是這個 form 是繼承來的,在父系跑全域 compenments / Controls 設定時能不能就做這種事? 父系不知道後代上面的東西名稱orz....

查詢時拿掉容易
for vJ := 0 to myPageControl.Pages[0].ControlCount - 1 do
begin
if (inPC.Pages[0].Controls[vJ] is TDBEdit) then
TDBedit(inPC.Pages[0].Controls[vJ]).OnExit := nil;
end;

要加回來的時囧到Orz..

原本以為用self, 配一個 FindProcedure 之類的
問題是根本沒有 FindProcedure 這東西囧rz, 估狗也估不到啥...

試驗:
TDBedit(inPC.Pages[0].Controls[vJ]).OnExit := self.FindComponent(inPC.Pages[0].Controls[vJ]).name).onexit;
當然,無效orz

難道要弄一個 TNotifyEvent 的 set 存起來再丟回去 Orz?
TWY
高階會員


發表:2
回覆:133
積分:152
註冊:2009-09-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-02-26 08:56:14 IP:59.120.xxx.xxx 訂閱
父親是文盲,辛苦工作送兒子去美國讀書,所以兒子比父親多了英語這項能力。如今兒子在英語應用上遇到問題,父親是無法直接給予幫助的,還是要靠兒子自行努力。我想這是(OO)不可違逆的法則吧。

換個角度想,若父親本身就具備英語能力,那所有後代子孫也會有。父親一變後代也跟著變。是否可以把你要的 OnExit Event 也寫一份在父類別上,讓所有子類別繼承這個 method (Overriding) 進而達到由父類別可以控制所有子類別的需求呢?

純以 OO 概念提出一些想法參考~

===================引 用 shininggod 文 章===================
可是這個 form 是繼承來的,在父系跑全域 compenments / Controls 設定時能不能就做這種事? 父系不知道後代上面的東西名稱orz....

編輯記錄
TWY 重新編輯於 2010-02-26 09:07:11, 註解 無‧
shininggod
一般會員


發表:16
回覆:20
積分:17
註冊:2009-05-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-02-26 10:49:36 IP:114.32.xxx.xxx 未訂閱
現在是用兩個array 吃掉
OnExitEventArray : array of TNotifyEvent;
OnExitEventNameArray : array of string;

要使用的時候用名子抓在assign回去...

當初是想說這東西create的時候已經存在,理論上能用指定名稱的方式抓到?
元件是可以,
procedure 應該也可以Orzzzz ...大失敗就是了
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-02-26 11:25:08 IP:112.104.xxx.xxx 未訂閱

[code delphi]
unit fMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Mask, DBCtrls;

type
THandlerObj = class
Name: string;
Handler: TNotifyEvent;
end;


TForm1 = class(TForm)
DBEdit1: TDBEdit;
DBEdit2: TDBEdit;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FList: TStringList;
public
procedure SwitchOnExitEventHandler(TURN_ON: Boolean);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
O: TDBEdit;
P: THandlerObj;
begin
FList := TStringList.Create;
FList.Sorted := True;
for I := 0 to ComponentCount-1 do
begin
if Components[I] is TDBedit then
begin
O := TDBEdit(Components[I]);
if Assigned(O.OnExit) then
begin
P := THandlerObj.Create;
P.Name := O.Name;
P.Handler := O.OnExit;
FList.AddObject(P.Name,P);
end;
end;
end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := 0 to FList.Count-1 do
FList.Objects[I].Free;
FreeAndNil(FList);
end;

procedure TForm1.SwitchOnExitEventHandler(TURN_ON: Boolean);
var
I,Index: Integer;
O: TDBEdit;
begin
case TURN_ON of
False:
begin
for I := 0 to ComponentCount-1 do
if Components[I] is TDBEdit then
TDBEdit(Components[I]).OnExit := nil;
end;
else begin
for I := 0 to ComponentCount-1 do
if Components[I] is TDBEdit then
begin
O := TDBEdit(Components[I]);
if FList.Find(O.Name,Index) then
O.OnExit := THandlerObj(FList.Objects[Index]).Handler;
end;
end;
end;
end;

end.
[/code]


謹供參考...^_^
TWY
高階會員


發表:2
回覆:133
積分:152
註冊:2009-09-02

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-02-26 12:16:11 IP:59.120.xxx.xxx 訂閱
大師一出手便知有沒有。
jow 大大這一行
O.OnExit := THandlerObj(FList.Objects[Index]).Handler;
輕鬆解決了 你 (shininggod) 這個問題
當然,無效orz

小弟亦受教了~


TWY
高階會員


發表:2
回覆:133
積分:152
註冊:2009-09-02

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-02-26 14:40:20 IP:59.120.xxx.xxx 訂閱
呵呵,看來 jow 大大的確是這樣做的喔,不過碼寫的工整潔明令人閱讀愉快。
我在想,若把 jow 的 Code 寫在你的父類別, SwitchOnExitEventHandler 改宣告 protedted 讓子類別都可呼叫,或許可以輕鬆漂亮的解決你的困擾,你可以試著想看看。


===================引 用 shininggod 文 章===================
難道要弄一個 TNotifyEvent 的 set 存起來再丟回去Orz?
TWY
高階會員


發表:2
回覆:133
積分:152
註冊:2009-09-02

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-02-26 15:26:10 IP:59.120.xxx.xxx 訂閱
剛有時間寫了一個小範例,不知道能否幫得上忙。(若你問題有因此獲得解決並欲給分,請給 jow,我是抄他的來改的 )
unFather.pas 是父類別 Form, unSon.pas 繼承自 unFather。主要程式碼都在 unFather.pas,而開關 OnExit Event 控制權仍在各子類別(應該是合理的),不過已經簡化、彈性化很多了。

[code delphi]
unit unFather;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TfrmFather = class(TForm)
Memo2: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
g_slEventContainer : TStringList;
public
{ Public declarations }
protected
procedure _SwitchOnExitEvent(isWork : Boolean);
end;

var
frmFather: TfrmFather;

implementation
{$R *.dfm}
type
TMyEventObj = class
Name : String;
EventReference : TNotifyEvent;
end;

procedure TfrmFather.FormCreate(Sender: TObject);
var
i : Integer;
myEventObj : TMyEventObj;
begin
g_slEventContainer := TStringList.Create;
g_slEventContainer.Sorted := True;

for i := 0 to ComponentCount-1 do begin
if (Components[i] is TEdit) and Assigned( (Components[i] as TEdit).OnExit ) then begin
myEventObj := TMyEventObj.Create;
myEventObj.Name := (Components[i] as TEdit).Name;
myEventObj.EventReference := (Components[i] as TEdit).OnExit;
g_slEventContainer.AddObject(myEventObj.Name,myEventObj);
end;
end;

end;
procedure TfrmFather.FormDestroy(Sender: TObject);
var
i : Integer;
begin
for i := 0 to g_slEventContainer.Count-1 do
g_slEventContainer.Objects[i].Free;
FreeAndNil(g_slEventContainer);
end;

procedure TfrmFather._SwitchOnExitEvent(isWork: Boolean);
var
i : Integer;
begin
for i := 0 to g_slEventContainer.Count-1 do begin
if isWork then
(FindComponent(TMyEventObj(g_slEventContainer.Objects[i]).Name) as TEdit).OnExit := TMyEventObj(g_slEventContainer.Objects[i]).EventReference
else
(FindComponent(TMyEventObj(g_slEventContainer.Objects[i]).Name) as TEdit).OnExit := Nil;
end;
end;

end.
[/code]

[code delphi]
unit unSon;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, unFather, StdCtrls;

type
TfrmSon = class(TfrmFather)
Memo1: TMemo;
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
Button2: TButton;
procedure Edit1Exit(Sender: TObject);
procedure Edit2Exit(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmSon: TfrmSon;

implementation
{$R *.dfm}
procedure TfrmSon.Edit1Exit(Sender: TObject);
begin
inherited;
Memo1.Lines.Add('Edit1.OnExit');
end;

procedure TfrmSon.Edit2Exit(Sender: TObject);
begin
inherited;
Memo1.Lines.Add('Edit2.OnExit');
end;

procedure TfrmSon.Button1Click(Sender: TObject);
begin
inherited;
_SwitchOnExitEvent(True); //讓所有 TEdit 恢復 OnExit Event
end;

procedure TfrmSon.Button2Click(Sender: TObject);
begin
inherited;
_SwitchOnExitEvent(False); //讓所有 TEdit 失去 OnExit Event
end;

end.
[/code]

shininggod
一般會員


發表:16
回覆:20
積分:17
註冊:2009-05-13

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-02-26 16:53:23 IP:114.32.xxx.xxx 未訂閱
除非 cc 公司肯弄個 findprocedure 的 function , 靠這個大概無望了XD

--------------------------------------------------------------------------------------------------

先存起來再叫出來用是可以....
我擔心的是假如有一大票onExit, 那每次都要繞loop一次..哪種神奇超慢主機會不會就被....

--------------------------------------------------------------------------------------------------

我原來的"想法"是, 這東西在create 完之後, 他的 event 都已經建立完 存在,
就算我換掉他, 應該只是 pointer 指向換位置, 原本的東西應該還是存在, 所以再指回去應該就可以用了

不過這想法對不對都是問題Orz

-------------------------------------------------------------------------------------------------

jow大勾的code真是漂亮, 我的code亂七八糟根本不敢貼上來(核爆),
系統時間:2024-03-29 21:04:13
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!