TListは項目が変更(追加・削除・抽出)されたときにNotifyメソッドが呼ばれます。
TListクラスを継承してNotifyメソッドを上書きすれば、項目が変更されたときに様々な処理を行うことができます。
次のTList1クラスは、TMyItemを項目に持ちます。
項目が削除されたときにメモリを解放します。
//サンプルコードに使用する型
struct TMyItem
{
TMyItem(TDateTime ATime) : Time(FormatDateTime("yyyymmddhhnnss", ATime)){}
UnicodeString Time;
};
//TListを継承してNotifyをオーバーライトしたクラス
//項目が削除されたらメモリを解放する
class TMyList1 : public TList
{
protected:
virtual void __fastcall Notify(void * Ptr, TListNotification Action)
{
switch (Action) {
case lnDeleted: //エントリがリストから削除された
delete (TMyItem*)Ptr;
break;
}
}
};
もう一工夫してみます。
Notifyメソッドをイベントにして、処理を簡単に差し替えることができるようにします。
次のTMyList2クラスはOnNotifyプロパティに、項目が変更されたときの処理を設定できます。
class TMyList2 : public TList
{
private:
typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender, void * Ptr, TListNotification Action);
TNotifyEvent FOnNotify;
protected:
//項目が変更されたとき
virtual void __fastcall Notify(void * Ptr, TListNotification Action)
{
//イベントが設定されているときは実行する
if (FOnNotify != NULL) { FOnNotify(this, Ptr, Action); }
}
public:
__fastcall TMyList2(void) : TList(), FOnNotify(NULL) { }
__fastcall virtual ~TMyList2() { Clear(); }
typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender, void * Ptr, TListNotification Action);
//項目が変更されたときに実行するイベント
__property TNotifyEvent OnNotify = {read=FOnNotify, write=FOnNotify};
};
サンプルプログラムでは、TMyList2クラスを使用して、項目が変更されたときにMemoコンポーネントに表示します。
class TForm1 : public TForm
{
…
private: // ユーザー宣言
TMyList2* FList;
void __fastcall OnListNofity(System::TObject* Sender, void * Ptr, TListNotification Action);
…
}
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner), FList(new TMyList2())
{
Memo1->Clear();
this->FList->OnNotify = this->OnListNofity;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnListNofity(System::TObject* Sender, void * Ptr, TListNotification Action)
{
TMyItem* item = (TMyItem*)Ptr;
switch (Action) {
case lnAdded: //エントリがリストに追加された
Memo1->Lines->Add("追加:" + item->Time);
break;
case lnDeleted: //エントリがリストから削除された
Memo1->Lines->Add("削除:" + item->Time);
delete item;
break;
case lnExtracted: //エントリがリストから抽出された
Memo1->Lines->Add("抽出:" + item->Time);
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonAddClick(TObject *Sender)
{
FList->Add(new TMyItem(Now()));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonRemoveClick(TObject *Sender)
{
FList->Delete(0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonExtractedClick(TObject *Sender)
{
FList->Extract(FList->Items[0]);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonClearClick(TObject *Sender)
{
FList->Clear();
}
2013年7月14日追記:コメント欄で教えていただいた点を修正しました。
lnExtractedが実行される条件がいまいちわかりませんでした。
ButtonExtractedの処理については、lnDeletedとlnAddedが順番に呼ばれるようですね。
lnExtractedは参照で呼ばれるとのことで、以下のようなコードも試したのですが、lnExtractedの処理とはなりませんでした。
—-
TMyItem *pList;
pList = (TMyItem *)FList->Items[0];
String str = pList->Time;
Memo1->Lines->Add(str);
—-
よろしければ、lnExtractedが呼ばれる処理についても教えていただければと思います。
FList->Extract()を使って処理したものに関して、lnExtractedの処理を通ることが確認できました。
指定の項目をリストから削除したい時に使うのですね。
yas様
お知らせいただきありがとうございます。
サンプルコードを修正します。
山本隆様
サンプルコードの修正ありがとうございました。
勉強になります。
TThreadListに変えたら、使えなくなったようです。
別のThreadでデータ処理をして、
MainスレッドでOnNotifyイベントを監視し、データの表示処理を行おうと思っておりますので、
TThreadListを使ったほうが良いでしょうか?
OnListNofity中の処理が終わらないと、帰ってこないようでした。
複数のスレッドが同時にアクセスすることがないので、TListでもOKでしょう。
TThreadListで項目の変更を取得するには、TThreadListのLockListメソッドでリストを取得して、OnNotifyイベントを設定すれば良さそうです。
Delphiの例になりますが、試してみました。
http://www.gesource.jp/weblog/?p=6647
Delphiは問題ないようですが、
C++ Builder XE4 Firemonkey HD app では動かないようですね