|
서영재 님이 쓰신 글 :
: MDI 프로그램에서 파일을 선택할때마다 Child 폼과 함께,
:
: Listv=new TListView(Application); //이렇게 생성합니다. 물론 헤더 파일에
: // TListView *Listv; 라고 명시했구요...
: Listv->Parent=PageControl1->Pages[Sheet]; //Sheet는 Pages의 수입니다. 즉, Child폼이
: // 생성할때마다 Pages가 생성되고 거기에 ListView가 생성됩니다.
:
: 아이템 추가에선, Child 폼에서,
:
: j=RxGIFAnimator1->Image->Count;
: for (i=0;i<j;i++){
: TListItem *Listi;
: MainForm->ImageL->Add(RxGIFAnimator1->Image->Frames[i]->Bitmap,NULL); //" i "는 for 문의 i 입니다.
: Listi=MainForm->Listv->Items->Add();
: }
:
: 즉 Child 폼에 버튼을 누르면 메인 폼에 만들어진 ListView 에 Gif 의 프레임을 하나하나씩
: 추가하게 만들었습니다.
:
: 근데, Child 폼이 하나일땐 상관이 없는데, 하나 이상이 되어버리면 동적으로ListView 도 많이
: 만들어져서 마지막에 만들어진ListView 에 밖에 추가가 되질 않더군요
:
: 만약에 ListView가 3개가 동적으로 만들어졌다면 2번째에 추가를 하고 싶은데, 어떻게 해야될지
: 몰라서...
: 위에 소스대로 하니깐 죽어도 마지막에밖에 추가가 되질 않더군요 ^.^
:
: 답변 부탁드립니다.
:
: 좋은 하루 되세요~
임펠리테리입니다.
메인폼에서 Listv 포인터로 리스트뷰를 반복해서 생성하고 있군요. 매번 리스트뷰를 생성할 때마다
동일한 Listv 포인터에 계속 값을 덮어쓰고 있으므로, Listv에는 항상 마지막으로 생성했던
리스트뷰 객체의 포인터만이 저장되어 있게 됩니다.
그런데 아이템을 생성하는 코드, 즉 Listi=MainForm->Listv->Items->Add(); 에서 보면, 이 Listv
객체에 아이템을 계속 추가하고 있군요. 그러니 당연히 마지막 리스트뷰에만 아이템이 추가되는
겁니다.
원하시는 것처럼 여러 리스트뷰에 각각의 경우에 따라 아이템을 추가하려고 하면 당연히 그 모든
리스트뷰 객체들의 포인터를 저장해두고 있어야 합니다. 말씀하신 경우에는 차일드폼 하나마다
페이지컨트롤의 페이지와 리스트뷰를 생성하므로, 차일드 폼 클래스 내에 리스트뷰에 대한 포인터
를 저장하고 있는 것이 좋겠습니다.
그리고 리스트뷰를 생성하는 코드도 차일드 폼의 생성시 발생하는 이벤트(OnCreate나 OnShow 등)
의 핸들러에서 작성해두면 전체 로직이 아주 깔끔하고 보기좋아지겠죠?
한가지 더 말씀드리면...
컴퍼넌트를 생성할 때 Owner 인자로 Application을 넘겨주는 것은 그리 좋은 방법이 아닙니다.
Owner는 Owner 자신이 파괴될 때 생성되고 있는 컴퍼넌트를 함께 파괴해주기 위해 지정하는 것으로
위에서 서영재님이 하신 것처럼 생성자의 인자로 Application을 넘겨주면 프로그램 전체가 끝날
때가 되어서야 리스트뷰가 파괴되게 되는 겁니다. 그래서 해당 컴퍼넌트가 한번 생성되고 나면
프로그램이 끝날 때까지 차지하고 있는 리소스를 반환하지 않게 되어 쓸데없이 리소스를 낭비하는
결과가 됩니다.
만약 이런 이유로, 다시 코딩으로 Owner를 지정해주었던 컴퍼넌트를 삭제하려고
delete 컴퍼넌트이름; 라고 하면, 나중에 Owner가 다시 파괴하려고 시도하므로 억세스바이얼레이션
의 이유가 됩니다.
그래서.. Owner를 지정하는 것은 상당히 주의를 요합니다. 예를 들어 서영재님이 원하시는 것처럼
차일드폼과 운명을 함께하는(?) 리스트뷰를 만들려면, 생성시에 Owner 인자로서 Application 대신
차일드폼을 넘겨줘야죠. 이때 차일드폼 클래스 내부에서 생성하고 있는 중이라면 this 포인터를
넘겨주면 되겠구요.
그럼 참고하시길...
|