全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:978
推到 Plurk!
推到 Facebook!

有沒有可能在物件本身的事件裡 delete 自己?

尚未結案
shinnuei
一般會員


發表:32
回覆:48
積分:21
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-10-20 23:28:04 IP:59.120.xxx.xxx 未訂閱
這一個需求是因為我會有很多動態產生的物件,我想在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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-10-21 09:41:22 IP:61.63.xxx.xxx 未訂閱
引言: 這一個需求是因為我會有很多動態產生的物件,我想在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;
    }
  }
}
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的事件,參著參著!
shinnuei
一般會員


發表:32
回覆:48
積分:21
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-10-21 13:12:30 IP:59.120.xxx.xxx 未訂閱
m8815010 版主你好: 對啊,我也是覺得滿有趣的。 一般的需求都是由其他的事件去刪除動態產生的物件、或者是在 FormClose、FormCloseQuery 之類的地方去刪除物件。 但是我這個需求是在程式內做訊息通知的顯示,而一般不重要的訊息,只要Click 就消失,比較重要的訊息,Click後會有更詳細的內容,這個詳細內容就可以正常delete 動態物件。 所以在 Click 一般的訊息時,就要刪除自己,此時繞路是比較麻煩的,我也有想到幾個繞路的做法,只是想提出來問一下,說不定會有另人意想不到的回答…
ENIX007
高階會員


發表:28
回覆:274
積分:185
註冊:2003-11-27

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-10-22 14:22:49 IP:220.228.xxx.xxx 未訂閱
shinnuei您好 之前小弟在另一篇討論中有遇過相同的問題  
 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55507
在滑鼠按按鈕的過程中最後觸發的事件是OnMouseUp,因此在該事件delete 就可以了...不過實用性不大,因為這樣就必須把Enter這個KeyCode攔掉才行... 還是參考版主的做法吧 <>補充: > <>補充 >,老話一句,還是參考版主的方法吧 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ 發表人 -
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
m8815010
版主


發表:99
回覆:372
積分:289
註冊:2003-11-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-10-22 16:46:10 IP:61.63.xxx.xxx 未訂閱
引言: 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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-10-22 17:46:48 IP:220.228.xxx.xxx 未訂閱
引言: 另外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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-10-25 14:40:34 IP:220.130.xxx.xxx 未訂閱
引言:
引言: 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 給 TMessage
 OldButtonWndProc(Message);
因為我的 OldButtonWndProc 己經宣告成
TWndMethod OldButtonWndProc[10];
我把 [code] OldButtonWndProc(Message); 改成 OldButtonWndProc[i](Message); 會出錯 AV
shinnuei
一般會員


發表:32
回覆:48
積分:21
註冊:2002-03-13

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-10-25 14:50:29 IP:220.130.xxx.xxx 未訂閱
其實這個作法也是可行的,而必須把 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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-10-25 16:12:21 IP:203.67.xxx.xxx 未訂閱
引言: 程式碼略.... 小弟試了一下,在 Form上面直接拉的元件果然是可以 delete 自己的。 再試run上面的程式碼,也是可以在自訂的OnClick 裡面把自己關掉。 但是上面這個做法唯一比較麻煩的地方,就是除了動態產生的物件需要記憶體,每一個動態產生的元件的 OldButtonWndProc 需要另外把他記起來。不然當OnClick時,只會對最後一個產生的元件有作用。 另外還有一個問題要請教的是,我剛剛要試著把上述程式碼改成動態產生多個元件,但是這一行卻不知道要怎麼 Assign 給 TMessage
 OldButtonWndProc(Message);
因為我的 OldButtonWndProc 己經宣告成
TWndMethod OldButtonWndProc[10];
我把
 
OldButtonWndProc(Message);
改成 
OldButtonWndProc[i](Message);
會出錯 AV
shinnuei你好< >: 當然當然,我只是舉例說明,真正是否合你用,可能就要再調整了< >! 你的需求應是會動態產生若干個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,有疑慮再研究研究吧!
shinnuei
一般會員


發表:32
回覆:48
積分:21
註冊:2002-03-13

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-10-28 22:12:05 IP:59.120.xxx.xxx 未訂閱
引言:
引言: 程式碼略.... 小弟試了一下,在 Form上面直接拉的元件果然是可以 delete 自己的。 再試run上面的程式碼,也是可以在自訂的OnClick 裡面把自己關掉。 但是上面這個做法唯一比較麻煩的地方,就是除了動態產生的物件需要記憶體,每一個動態產生的元件的 OldButtonWndProc 需要另外把他記起來。不然當OnClick時,只會對最後一個產生的元件有作用。 另外還有一個問題要請教的是,我剛剛要試著把上述程式碼改成動態產生多個元件,但是這一行卻不知道要怎麼 Assign 給 TMessage
 OldButtonWndProc(Message);
因為我的 OldButtonWndProc 己經宣告成
TWndMethod OldButtonWndProc[10];
我把
 
OldButtonWndProc(Message);
改成 
OldButtonWndProc[i](Message);
會出錯 AV
shinnuei你好< >: 當然當然,我只是舉例說明,真正是否合你用,可能就要再調整了< >! 你的需求應是會動態產生若干個TButton元件(假設是這元件),然後這每個Button都可以在onclick事件中自已刪除自已! 那我前範例只有一個button,所以你要同時有多個的話,我想直接新寫一個TButton物件應該較方便了,就不需要concern你的 TWndMethod OldButtonWndProc[10]; 這種問題了! class="code">程式碼略… 這樣寫好新的TButton元件後,要用幾個就new幾個,每個new出來後就有在onclick事件中delete本身的功能,應該比較方便! After all,有疑慮再研究研究吧! < face="Verdana, Arial, Helvetica"> 謝謝 m8815010,每次都是先把問題解決再上來看,結果每次都是把我的方法一再推翻,您的方法比較方便哦~~~
系統時間:2024-05-19 9:12:45
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!