如何使用WriteComponent儲存內含TList的物件 |
尚未結案
|
shychef
一般會員 ![]() ![]() 發表:5 回覆:10 積分:3 註冊:2004-10-02 發送簡訊給我 |
各位大大:
小人在下我建立一個Class如下: //------------prjdata.h--------------
class TPrj : public TComponent
{
private:
AnsiString FPrj_Name;
AnsiString FPrj_Comment;
public:
TList *pTaskList;
__fastcall TPrj(AnsiString);
__fastcall TPrj();
__fastcall ~TPrj();
__published:
__property AnsiString Prj_Name = {read=FPrj_Name, write=FPrj_Name};
__property AnsiString Prj_Comment = {read=FPrj_Comment , write=FPrj_Comment};
}; 當按下button2後,則用WriteComponent將aPrj物件儲存起來
當按下button3後,則用ReadComponent將物件內容丟到bPrj物件儲存起來
//------------project.cpp--------------
TPrj* aPrj=new TPrj();
void __fastcall TMDIChild::Button2Click(TObject *Sender)
{
TMemoryStream* buffer= new TMemoryStream();
buffer->WriteComponent(aPrj);
buffer->SaveToFile("save.dat");
delete buffer;
} TPrj* bPrj;
void __fastcall TMDIChild::Button3Click(TObject *Sender)
{
bPrj = new TPrj();
TMemoryStream* buffer = new TMemoryStream() ;
try{
buffer->Position = 0;
buffer->LoadFromFile("asd.chr");
buffer->ReadComponent(bPrj);
}
__finally{
delete buffer,bPrj;
}
} 程式到目前為止都是正常無誤的,可正常寫入,也可正常讀出。
現在問題來了。
在class TPrj 中有一個TList *pTaskList;
pTaskList裏面裝的又是一個類別,內容如下:
很明顯的,當我使用WriteComponent時,是無法將這個TList裏裝的類別的資料也一起儲存。
用DefineProperties有辦法解決嗎?請大大們為不才解惑 //------------taskdata.h--------------
class TTask : public TComponent
{
private:
AnsiString FTsk_Name;
AnsiString FTsk_Type;
public:
TList *pPouList;
__fastcall TTask(AnsiString);
__fastcall ~TTask();
__published:
__property AnsiString Tsk_Name = {read=FTsk_Name, write=FTsk_Name};
__property AnsiString Tsk_Type = {read=FTsk_Type, write=FTsk_Type};
};
|
taishyang
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:377 回覆:5490 積分:4563 註冊:2002-10-08 發送簡訊給我 |
|
justdo
高階會員 ![]() ![]() ![]() ![]() 發表:2 回覆:359 積分:222 註冊:2004-08-17 發送簡訊給我 |
TList 裡面存放 void* 的東西,顯然無法透過這種指標獲知內部存放的東西到底是什麼,建議換個容器來存放,另外,你是存放什麼東西的指標? 另外,你的程式我編不起來(真是慚愧... )
TPrj型別繼承TComponent,當產生新物件時TComponent需要一個TComponent* Owner,你是怎麼給他的? 還有我覺得你光是用 buffer->WriteComponent(aPrj);
並不會儲存FPrj_Name跟FPrj_Comment這兩個物件
從文件上看來,應該要 override WriteState()
然後在這個函式內寫好儲存TPrj內部成員的程式碼
不過我測試的類別想繼承TComponent都失敗,所以無從測起...
|
pwipwi
版主 ![]() ![]() ![]() ![]() ![]() 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
TList並不包含在Delphi定義的property資料型,無法用WriteComponent存。
可以用的資料型可以參考以下的程式片斷:
switch(TypeKind) { case tkUnknown: return "Unknown"; case tkInteger: return "Integer"; case tkChar: return "Char"; case tkEnumeration: return "Enumeration"; case tkFloat: return "Float"; case tkString: return "String"; case tkSet: return "Set"; case tkClass: return "Class"; case tkMethod: return "Method"; case tkWChar: return "WideChar"; case tkLString: return "LongString"; case tkWString: return "WideString"; case tkVariant: return "Variant"; case tkArray: return "Array"; case tkRecord: return "Record"; case tkInterface: return "Interface"; case tkInt64: return "Int64"; case tkDynArray: return "DynArray"; } |
shychef
一般會員 ![]() ![]() 發表:5 回覆:10 積分:3 註冊:2004-10-02 發送簡訊給我 |
|
shychef
一般會員 ![]() ![]() 發表:5 回覆:10 積分:3 註冊:2004-10-02 發送簡訊給我 |
TO: justdo前輩
謝謝您的回應 ??-----
TPrj型別繼承TComponent,當產生新物件時TComponent需要一個TComponent* Owner,你是怎麼給他的?
//------
產生新物件時,它的owner我是設NULL ??---------
TList存的是什麼指標?
//----------
TList 裏面存的指標是一個指向TTask(我自訂的)的物件。 為了簡化我的問題,所以貼出來的程式碼是經過精簡過的,
所以有些地方沒交待那麼清楚,非常抱歉。
其實我要寫的是一個編輯器,使用者可建立一個project。
這個project中可管理多個task,使用者可在每個task建立network區塊編輯程式。
我之所以會繼承TComponent,主要就是為了使用WriteComponent,
因為我想把整個project當成一個物件,當使用者要儲存編輯內容時就將整個元件儲存起來就好了。
我有上傳一張示意圖,如下,大大們看了應該就會比較明白我問的問題。
http://140.115.80.13/~shychef/question.jpg 另外,我的屬性都有寫在__published:下面,所以SaveToFile及LoadFromFile,都是正常的。
TList* pTaskList這個搞不定。 發表人 - shychef 於 2005/08/03 10:56:04 發表人 - shychef 於 2005/08/03 11:05:45
|
shychef
一般會員 ![]() ![]() 發表:5 回覆:10 積分:3 註冊:2004-10-02 發送簡訊給我 |
TO:pwipwi前輩
依您所說: TList並不包含在Delphi定義的property資料型,無法用WriteComponent存。
但是否有辦法用DefineProperties克服。
下面是我一個朋友在六年前寫的,因為已經跟他失聯,所以沒法子請叫他。
不知前輩對下列的程式有何看法。 注意最後那行
__property TMemoryStream *Body={read=GetBody, write=SetBody}; 在產生C4MsgAppendix物件後,就可以用 xxx->Body->Memory
class PACKAGE TC4MsgAppendix : public TComponent { private: // property variable declaration AnsiString FCatalog; // 判斷類別及編號 AnsiString FReference; // 參考資料 int FKind; // 配佈 TMemoryStream *FBody; // 訊息實體 // property method declaration //---------------- TMemoryStream* __fastcall GetBody(void) { if (FBody == NULL) FBody = new TMemoryStream; return FBody; }; void __fastcall SetBody(TMemoryStream *Value) { if (FBody && Value) { FBody->LoadFromStream(Value); } }; //---------------- void __fastcall ReadData(TStream* Stream) { Body->LoadFromStream(Stream); }; void __fastcall WriteData(TStream* Stream) { Body->SaveToStream(Stream); }; //---------------- int __fastcall GetKind(void) { return FKind; }; void __fastcall SetKind(int Value) { FKind = Value; }; public: __fastcall TC4MsgAppendix() : TComponent(NULL) {}; virtual void __fastcall DefineProperties(TFiler* Filer) { Filer->DefineBinaryProperty("Body->Memory", ReadData, WriteData, true); } __published: __property AnsiString Catalog={read=FCatalog, write=FCatalog}; __property AnsiString Reference={read=FReference, write=FReference}; __property int Kind={read=GetKind, write=SetKind, default = 0}; __property TMemoryStream *Body={read=GetBody, write=SetBody}; };最後,為什麼我上傳一張圖檔不會出現? 好奇怪哦! 有顯示上傳成功耶 |
justdo
高階會員 ![]() ![]() ![]() ![]() 發表:2 回覆:359 積分:222 註冊:2004-08-17 發送簡訊給我 |
同上一篇文章可以用 DefineProperty 定義處理 pPouList 的兩個函式
然後分別處理 ReadComponent 和 WriteComponent 時對 pPouList 該如何處理 若你 TTask 有繼承 TComponent,那麼應該在處理 WriteComponent 時,將pPouList內部的元素一一呼叫 Writer->WriteComponent(pPouList->Items[i])即可
若沒有繼承 TComponent,只是簡單的 struct,則直接用 Writer->Write 就行了,以下是測試程式
#include備註:以上程式碼未最佳化、也未歸還使用的記憶體、僅考慮TList含有一個元素而已 |
shychef
一般會員 ![]() ![]() 發表:5 回覆:10 積分:3 註冊:2004-10-02 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |