질문을 미처 못 봤던 것 같군요.. ^^ 죄송함다..
답변을 어디다 적을까 한참 망설이다가.. 질문이 너무 뒤로 가버려서 그냥 여기다
적겠습니다.. (아.. 남들눈을 의식하는 패패루.. 케케케)
음.. 일단, VirtualTree는 패러다임 자체가 기존의 트리뷰와는 많이 다릅니다.
그래서 만해 님이 혼돈하시는 부분이 있는 것 같군요.
어떻게 설명드려야 좋을지 저도 좀 고민하게 되는데... 음....
으그.. 한참 써 내려가다가 몽땅 지웠슴다.. ㅠ ㅠ 일반적인 사용법은 따로 다루도록
하고, 님이 질문하신 내용에 한정지어서 답변 드리겠습니다.
님이 적으신 코드는 메모리 누수까지 동반하고 문제가 좀 심각해 보입니다.
TVirtualTree는 노드가 생성될 때 각 노드마다 NodeDataSize에 지정된 만큼의 크기로
메모리를 할당합니다.
따라서 님이 적으신 코드는 노드가 하나 생성될 때 마다 TTreeData의 크기인 12byte씩
메모리를 할당을 하게 되는데 엉뚱하게도 여기에 TTreeData* 타입(4byte)의 데이터를
대입하는 아주 이상한 구조입니다.
다음과 같이 하셔야겠죠.
두가지 접근 방향을 제시하겠습니다.
1. TTreeData의 생성을 TVirtualTree에 맡기는 방법
void __fastcall TForm1::OnCreate(TObject* Sender)
{
VirtualStringTree2->NodeDataSize = sizeof(TTreeData); //sizeof를 눈여겨 보세요 12byte
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TVirtualNode* pNode = VirtualStringTree2->AddChild(NULL,NULL); // 루트에 노드 생성
// 옛날 버전에서는 AddChild의 파라미터로 UserData는 넘길 수 없었습니다. 하여간..
// 다음과 같이 써도 무방...
// TVirtualNode* pNode = VirtualStringTree2->AddChild(NULL); //루트에 노드 생성.
// 노드가 추가되면서 TTreeData를 담을 수 있는 12byte만큼의 메모리가 할당됩니다.
// 따라서 new를 쓸 필요가 없지만 한가지 주의하십시요.
// TTreeData를 struct를 안쓰고 class로 구현했을 경우, TTreeData의 컨스트럭터는 동작을
// 할까요 안할까요??? ^^ 당연히 동작 안합니다!!! 이런 경우는 다른방법을 써야 합니다.
// 그리고 할당된 메모리의 파괴도 역시 TVirtualTree가 담당합니다.
// TTreeData의 디스트럭터는 동작할까요?? 당연히 동작 안합니다.
TTreeData* pData = (TTreeData*)(VirtualStringTree2->GetNodeData(pNode));
pData->Data = "Test";
pData->ID = 1;
pData->Depth = 1;
}
이렇게 채우는 겁니다. new로 TTreeData를 생성하는 부분이 전혀 없지만 정상 동작합니다.
아니면 다음과 같이 합니다.
2. 사용자가 직접 메모리 관리하기.. 포인터만 저장
void __fastcall TForm1::OnCreate(TObject* Sender)
{
VirtualStringTree2->NodeDataSize = sizeof(TTreeData*); //sizeof를 눈여겨 보세요 4byte
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TTreeData* pData = new TTreeData();
pData->Data = "Test";
pData->ID = 1;
pData->Depth = 1;
TVirtualNode* pNode = VirtualStringTree2->AddChild(NULL,pData); // 루트에 노드 생성
}
메모리 누수를 막기 위해 당연히 OnFreeNode에
TTreeData* pData = *((TTreeData**)(VirtualStringTree2->GetNodeData(Node)));
delete pData;
와 같은 코딩이 필요하겠죠. 포인터의 포인터를 쓴 것을 눈여겨 보셔야 할겁니다.
어쨌건, 데이터를 이렇게 넣었다고 화면에 뭔가 나올걸 기대하시면 안됩니다.
어찌보믄 엄청 불합리해 보이지만 이 성질을 잘 이용하면 정말 눈알튀어나오는걸 만들 수
있습니다.
화면에 뭔가 뿌려주려면 다음과 같이 하시면 됩니다.
OnGetText 이벤트에 코딩합니다.
void __fastcall TForm1::vstTestGetText(TBaseVirtualTree *Sender,
PVirtualNode Node, int Column, TVSTTextType TextType,
WideString &CellText)
{
// 첫번째 경우를 쓴 겁니다.
TTreeData* pData = (TTreeData*)(VirtualStringTree2->GetNodeData(pNode));
switch (Column)
{
case 0: // 첫번째 칼럼인 경우
CellText = pData->Data;
break;
case 1: // 두번째 칼럼인 경우
CellText = "아뒤"+IntToStr(pData->ID);
break;
case 1: // 세번째 칼럼인 경우
CellText = "기피"+IntToStr(pData->Depth, 0);
break;
}
}
이젠 화면에 뭔가 나오는 것을 볼 수 있을겁니다.
TTreeView와 간단히 비교해 보면,
루트노드에 100만개를 표시할 때를 생각해 보죠.
TTreeView에서는 100만번 루프를 돌리면서 TTreeView->Items->AddChild()함수를
100만번 호출, 각각의 100만개의 캡션에 뭔가 값을 넣어줘야 합니다.
TTreeView를 단순히 내가 따로 관리하는 데이터를 표시해 주는데만 쓴다면, 어마
어마한 메모리 낭비에 엄청난 시간이 필요하겠죠.
하지만 TVirtualTree에서는 화면 표시에 필요한 만큼만 OnGetText이벤트가 호출
됩니다. 화면 표시를 위해 캡션데이터를 복사할 필요도 없고, 자신이 갖춰놓은
자료구조에 TVirtualTree가 달라붙는 형식으로 동작시킬 수 있죠.
100만개 추가해도 화면에 달랑 10개만 보인다면 10개 데이터 접근 속도밖에 안걸
리는 겁니다.
아.. 졸려.. 나중에 안졸릴때.. 이런건 아예 강의가 필요할 것 같은데...
하여간.. 필요하다면 나중에 좀 더 자세히 알려드리겠습니다.
여기 계신 많은 고수님들을 마구 괴롭히세요.. 애꿎은 저는 좀 봐주시구요. 헤헤
PS. 만해님은 Virtual Tree 설치 제대로 되시던가요??
전 dsgnintf는 라이브러리 패스에 source\ToolsAPI를 첨가해서 되는데 그담에
colnedit는 죽어라구 안됩니다.. 아무래도 정답은 dsnide50.lib가 있어야 하는
분위긴데.. 어흑... 디자인 타임 패키지니까 좀 빠져도 상관 없긴 하지만 그래두
기분 꿀꿀... 그쪽 뉴스그룹에도 동일한 문제가 올라왔는데 다들 답은 안주구
엉뚱한 얘기들만 하고 있더군요.. 우이쓍~~~
만해 님이 쓰신 글 : 카피한겁니다.
안녕하세요 만해입니다.
어제 컴포넌트 자료실에 있는 VirtualTree 컴포넌트를 다운 받아서
천신만고 끝에 깔아서
지금 사용하고 있는데요
그냥 단순히 자료 넣는건 알겠는데
제가 원하는 형식으로 자료를 넣을려니깐
잘 안되네요
지금 도움말도 뒤지고 했는데도 잘 모르곘고
도움 부탁 드립니다.
typedef struct
{
AnsiString Data;
LONG ID;
LONG Depth;
}TTreeData;
이건 헤더 파일에 정의된 데이타 형이고요
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TTreeData* Data = new TTreeData;
Data->Data = "Test";
Data->ID = 1;
Data->Depth = 1;
VirtualStringTree2->NodeDataSize = sizeof(Data);
VirtualStringTree2->AddChild(NULL,(void*)Data);
}
이건 자료를 입력 하는 루틴입니다.
분명히 도움말에 나온것 처럼 구조제를 만들어서 집어 넣는데도
제가 원하는 식으로는 안나오고
그냥 기본형만 나오네요
고수님들의 도움 부탁 드립니다.
|