有沒有可能在物件本身的事件裡 delete 自己? |
尚未結案
|
shinnuei
一般會員 發表:32 回覆:48 積分:21 註冊:2002-03-13 發送簡訊給我 |
這一個需求是因為我會有很多動態產生的物件,我想在OnClick 時,就把自己給 delete 掉,但是都會出現 AV,想繞路又覺得麻煩,想請教有沒有這個可能呢?
void __fastcall TForm1::pnlMsgQueueClick(TObject *Sender) { for(int i=0; i < count;i ) { if(pnlMsgQueue[i]->Caption == ( (TPanel *) Sender)->Caption) { delete pnlMsgQueue[i]; pnlMsgQueue[i] = NULL; } } } |
m8815010
版主 發表:99 回覆:372 積分:289 註冊:2003-11-13 發送簡訊給我 |
引言: 這一個需求是因為我會有很多動態產生的物件,我想在OnClick 時,就把自己給 delete 掉,但是都會出現 AV,想繞路又覺得麻煩,想請教有沒有這個可能呢?shinnuei你好< >: 我覺得這問題還滿有趣的,以前都沒想過< >! 試了一下,應該還是不行,不是delete button時出錯。而是好像是整個click事件結束後, 好像會有一個return的動作,告訴原呼叫button這個事件已經結束了,但卻找不到原button 了(因為被delete了),於是出錯了! 所以目前我個人認為還是要等事件結束才能做 >! < class="code"> Unit1.h ~~ class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; void __fastcall Button1Click(TObject *Sender); void __fastcall FormCreate(TObject *Sender); private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); void __fastcall BtnClick(TObject *Sender); <--共同button click事件 void __fastcall AppMessage(tagMSG &Msg,bool &Handled);<--application事件 }; Unit1.cpp ~~ TForm1 *Form1; TButton* btn1; //動態button //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { btn1=new TButton(this); //開始new一個動態button btn1->Parent=this; btn1->Caption="新增一號"; btn1->this->BtnClick; //指定動態button的click事件 } //--------------------------------------------------------------------------- void __fastcall TForm1::BtnClick(TObject *Sender) { PostMessage(Application->Handle,WM_USER 1234,0,(LONG)Sender); //在click事件內要求delete本身 } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { Application->AppMessage; //application事件assign } //--------------------------------------------------------------------------- void __fastcall TForm1::AppMessage(tagMSG &Msg,bool &Handled) { if (Msg.message==WM_USER 1234) { //真正delete button物件的地方 TButton* nowbtn; nowbtn=(TButton*)Msg.lParam; delete nowbtn; nowbtn=NULL; } } 所以真正多寫的只有application的事件,參著參著!void __fastcall TForm1::pnlMsgQueueClick(TObject *Sender) { for(int i=0; i < count;i ) { if(pnlMsgQueue[i]->Caption == ( (TPanel *) Sender)->Caption) { delete pnlMsgQueue[i]; pnlMsgQueue[i] = NULL; } } } |
shinnuei
一般會員 發表:32 回覆:48 積分:21 註冊:2002-03-13 發送簡訊給我 |
m8815010 版主你好:
對啊,我也是覺得滿有趣的。
一般的需求都是由其他的事件去刪除動態產生的物件、或者是在 FormClose、FormCloseQuery 之類的地方去刪除物件。
但是我這個需求是在程式內做訊息通知的顯示,而一般不重要的訊息,只要Click 就消失,比較重要的訊息,Click後會有更詳細的內容,這個詳細內容就可以正常delete 動態物件。
所以在 Click 一般的訊息時,就要刪除自己,此時繞路是比較麻煩的,我也有想到幾個繞路的做法,只是想提出來問一下,說不定會有另人意想不到的回答…
|
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
shinnuei您好
之前小弟在另一篇討論中有遇過相同的問題
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55507在滑鼠按按鈕的過程中最後觸發的事件是OnMouseUp,因此在該事件delete 就可以了...不過實用性不大,因為這樣就必須把Enter這個KeyCode攔掉才行... 還是參考版主的做法吧 <>補充: >> <>補充 >,老話一句,還是參考版主的方法吧> 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ 發表人 -
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ |
m8815010
版主 發表:99 回覆:372 積分:289 註冊:2003-11-13 發送簡訊給我 |
引言: m8815010 版主你好: 對啊,我也是覺得滿有趣的。 一般的需求都是由其他的事件去刪除動態產生的物件、或者是在 FormClose、FormCloseQuery 之類的地方去刪除物件。 但是我這個需求是在程式內做訊息通知的顯示,而一般不重要的訊息,只要Click 就消失,比較重要的訊息,Click後會有更詳細的內容,這個詳細內容就可以正常delete 動態物件。 所以在 Click 一般的訊息時,就要刪除自己,此時繞路是比較麻煩的,我也有想到幾個繞路的做法,只是想提出來問一下,說不定會有另人意想不到的回答… >>< face="Verdana, Arial, Helvetica"> 嗯,EMIX007的做法我覺得還ok了,用mouseup事件去取代click事件不錯呀!要挑一點的話 就是要擋掉一些特意的做法而已:如按下button後,等到滑鼠離開button才放開,或是先 在其它area按下滑鼠,再移到button上方,再放開滑鼠! 另外EMIX007說的:必須把Enter這個KeyCode攔掉才行 我就不解了! >: < class="code"> 1. 如果是直接用拉的TButton元件的話,是可以在本身的onclick事件中delete本身的,那 為什麼用new的TButton元件不行?我想以這個方向去想應該不錯! 2. TButton的Onclick事件是這樣的: __property Classes::TNotifyEvent OnClick = {read=FOnClick, write=FOnClick, stored=IsOnClickStored}; 也就是感覺onclick事件結束後會有個return或是restore的動作,但由於原Button的memory allocation已經沒有 了,所以造成了memory access的error! 那解決之道應該可以用重寫onclick事件,避掉return的問題! Builder的寫法不太會,只會這樣寫: Unit1.h ~~ class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; void __fastcall Button1Click(TObject *Sender); private: // User declarations //add this line TWndMethod OldButtonWndProc; void __fastcall ButtonWndProc(TMessage& Message); //add this line public: // User declarations __fastcall TForm1(TComponent* Owner); }; Unit1.cpp ~~ TButton* btn1; //動態button變數 bool click_now; //是否按下button flag //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { btn1=new TButton(this); //new 這個動態button btn1->Parent=this; btn1->Caption="可惡小按鈕"; OldButtonWndProc=btn1->WindowProc; //assign新的onclick事件 btn1->WindowProc=ButtonWndProc; } //--------------------------------------------------------------------------- void __fastcall TForm1::ButtonWndProc(TMessage& Message) //新的button onclick事件 { OldButtonWndProc(Message); if (Message.Msg==WM_LBUTTONDOWN) { click_now=true; } if (Message.Msg==WM_LBUTTONUP && click_now) { POINT p; GetCursorPos(&p); RECT rect; GetWindowRect(btn1->Handle,&rect); if (PtInRect(&rect,p)) { delete btn1; //在事件中移除本身 btn1=NULL; click_now=false; } } } 嗯,就這樣,沒什麼新皮條了! 發表人 - |
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
引言: 另外EMIX007說的:必須把Enter這個KeyCode攔掉才行 我就不解了!關於這點小弟說明一下,在Form上放一個Button(用new的也行),Focus設定 在Button,開啟Builder內建的WinSight程式觀察,使用滑鼠按下按鈕時, 依序觸發OnMouseDown,OnClick,OnMouseUp,但是!!如果按下Enter來"按"按鈕時, 並不會觸發OnKeyDown和OnKeyUp事件...而只有OnClick事件而已... 因此如果改寫到OnMouseUp的話,必須防止使用者Focus在Button時按下Enter 鍵...當然這種做法很詭異,不建議使用 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ |
shinnuei
一般會員 發表:32 回覆:48 積分:21 註冊:2002-03-13 發送簡訊給我 |
引言:引言: m8815010 版主你好: 對啊,我也是覺得滿有趣的。 一般的需求都是由其他的事件去刪除動態產生的物件、或者是在 FormClose、FormCloseQuery 之類的地方去刪除物件。 但是我這個需求是在程式內做訊息通知的顯示,而一般不重要的訊息,只要Click 就消失,比較重要的訊息,Click後會有更詳細的內容,這個詳細內容就可以正常delete 動態物件。 所以在 Click 一般的訊息時,就要刪除自己,此時繞路是比較麻煩的,我也有想到幾個繞路的做法,只是想提出來問一下,說不定會有另人意想不到的回答… >>< face="Verdana, Arial, Helvetica"> 嗯,EMIX007的做法我覺得還ok了,用mouseup事件去取代click事件不錯呀!要挑一點的話 就是要擋掉一些特意的做法而已:如按下button後,等到滑鼠離開button才放開,或是先 在其它area按下滑鼠,再移到button上方,再放開滑鼠! 另外EMIX007說的:必須把Enter這個KeyCode攔掉才行 我就不解了! >: < class="code"> 1. 如果是直接用拉的TButton元件的話,是可以在本身的onclick事件中delete本身的,那 為什麼用new的TButton元件不行?我想以這個方向去想應該不錯! 2. TButton的Onclick事件是這樣的: __property Classes::TNotifyEvent OnClick = {read=FOnClick, write=FOnClick, stored=IsOnClickStored}; 也就是感覺onclick事件結束後會有個return或是restore的動作,但由於原Button的memory allocation已經沒有 了,所以造成了memory access的error! 那解決之道應該可以用重寫onclick事件,避掉return的問題! Builder的寫法不太會,只會這樣寫: 程式碼略....小弟試了一下,在 Form上面直接拉的元件果然是可以 delete 自己的。 再試run上面的程式碼,也是可以在自訂的OnClick 裡面把自己關掉。 但是上面這個做法唯一比較麻煩的地方,就是除了動態產生的物件需要記憶體,每一個動態產生的元件的 OldButtonWndProc 需要另外把他記起來。不然當OnClick時,只會對最後一個產生的元件有作用。 另外還有一個問題要請教的是,我剛剛要試著把上述程式碼改成動態產生多個元件,但是這一行卻不知道要怎麼 Assign 給 TMessageOldButtonWndProc(Message);因為我的 OldButtonWndProc 己經宣告成TWndMethod OldButtonWndProc[10];我把 [code] OldButtonWndProc(Message); 改成 OldButtonWndProc[i](Message); 會出錯 AV |
shinnuei
一般會員 發表:32 回覆:48 積分:21 註冊:2002-03-13 發送簡訊給我 |
其實這個作法也是可行的,而必須把 Enter 的 KeyCode 攔掉的缺點,因為小弟的應用上不需要 Focus 到 Button 上,所以我把 TabStop = false;所以也不用去攔掉VK_RETURN,要是真的有需要 TabStop = true,攔掉 VK_RETURN 也不會很麻煩,謝謝您提供小弟這個方向。
引言: shinnuei您好 之前小弟在另一篇討論中有遇過相同的問題http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55507在滑鼠按按鈕的過程中最後觸發的事件是OnMouseUp,因此在該事件delete 就可以了...不過實用性不大,因為這樣就必須把Enter這個KeyCode攔掉才行... 還是參考版主的做法吧 <>補充: >> <>補充 >,老話一句,還是參考版主的方法吧> 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ 發表人 - >>< face="Verdana, Arial, Helvetica"> |
m8815010
版主 發表:99 回覆:372 積分:289 註冊:2003-11-13 發送簡訊給我 |
引言: 程式碼略.... 小弟試了一下,在 Form上面直接拉的元件果然是可以 delete 自己的。 再試run上面的程式碼,也是可以在自訂的OnClick 裡面把自己關掉。 但是上面這個做法唯一比較麻煩的地方,就是除了動態產生的物件需要記憶體,每一個動態產生的元件的 OldButtonWndProc 需要另外把他記起來。不然當OnClick時,只會對最後一個產生的元件有作用。 另外還有一個問題要請教的是,我剛剛要試著把上述程式碼改成動態產生多個元件,但是這一行卻不知道要怎麼 Assign 給 TMessageshinnuei你好< >: 當然當然,我只是舉例說明,真正是否合你用,可能就要再調整了< >! 你的需求應是會動態產生若干個TButton元件(假設是這元件),然後這每個Button都可以在onclick事件中自已刪除自已! 那我前範例只有一個button,所以你要同時有多個的話,我想直接新寫一個TButton物件應該較方便了,就不需要concern你的 TWndMethod OldButtonWndProc[10]; 這種問題了! class="code"> Unit1.h ~~ class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; void __fastcall Button1Click(TObject *Sender); private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); }; class TMyButton : public TButton //新的TButton元件 { private: bool click_now; //承上意思 TWndMethod OldButtonWndProc; //承上意思 void __fastcall ButtonWndProc(TMessage& Message); //承上意思 public: __fastcall TMyButton(TComponent* Owner); //constructor }; ~~ Unit1.cpp ~~ TForm1 *Form1; TMyButton* btn[5]; //動態button變數 5個 //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int gap=0; for (int i=0;i<5;i ) { btn[i]=new TMyButton(this); //new動態button btn[i]->Parent=this; btn[i]->Caption="Button" IntToStr(i); btn[i]->Left=gap; gap =100; } } //--------------------------------------------------------------------------- __fastcall TMyButton::TMyButton(TComponent* Owner) : TButton(Owner) { click_now=false; OldButtonWndProc=WindowProc; WindowProc=ButtonWndProc; } //--------------------------------------------------------------------------- void __fastcall TMyButton::ButtonWndProc(TMessage& Message) //新的button onclick事件 { OldButtonWndProc(Message); if (Message.Msg==WM_LBUTTONDOWN) { click_now=true; } if (Message.Msg==WM_LBUTTONUP && click_now) { POINT p; GetCursorPos(&p); RECT rect; GetWindowRect(this->Handle,&rect); if (PtInRect(&rect,p)) delete this; //在事件中移除本身 } } 這樣寫好新的TButton元件後,要用幾個就new幾個,每個new出來後就有在onclick事件中delete本身的功能,應該比較方便! After all,有疑慮再研究研究吧!OldButtonWndProc(Message);因為我的 OldButtonWndProc 己經宣告成TWndMethod OldButtonWndProc[10];我把OldButtonWndProc(Message); 改成 OldButtonWndProc[i](Message); 會出錯 AV |
shinnuei
一般會員 發表:32 回覆:48 積分:21 註冊:2002-03-13 發送簡訊給我 |
引言:引言: 程式碼略.... 小弟試了一下,在 Form上面直接拉的元件果然是可以 delete 自己的。 再試run上面的程式碼,也是可以在自訂的OnClick 裡面把自己關掉。 但是上面這個做法唯一比較麻煩的地方,就是除了動態產生的物件需要記憶體,每一個動態產生的元件的 OldButtonWndProc 需要另外把他記起來。不然當OnClick時,只會對最後一個產生的元件有作用。 另外還有一個問題要請教的是,我剛剛要試著把上述程式碼改成動態產生多個元件,但是這一行卻不知道要怎麼 Assign 給 TMessageshinnuei你好< >: 當然當然,我只是舉例說明,真正是否合你用,可能就要再調整了< >! 你的需求應是會動態產生若干個TButton元件(假設是這元件),然後這每個Button都可以在onclick事件中自已刪除自已! 那我前範例只有一個button,所以你要同時有多個的話,我想直接新寫一個TButton物件應該較方便了,就不需要concern你的 TWndMethod OldButtonWndProc[10]; 這種問題了! class="code">程式碼略… 這樣寫好新的TButton元件後,要用幾個就new幾個,每個new出來後就有在onclick事件中delete本身的功能,應該比較方便! After all,有疑慮再研究研究吧! >>< face="Verdana, Arial, Helvetica"> 謝謝 m8815010,每次都是先把問題解決再上來看,結果每次都是把我的方法一再推翻,您的方法比較方便哦~~~OldButtonWndProc(Message);因為我的 OldButtonWndProc 己經宣告成TWndMethod OldButtonWndProc[10];我把OldButtonWndProc(Message); 改成 OldButtonWndProc[i](Message); 會出錯 AV |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |