참고문헌 : Visual C++ 6 완벽가이드

 

2. 트리컨트롤(TreeControl)

 트리 컨트롤은 계층구조를 가지는 데이터를 표시하는데 적합합니다. 계층구조를 가지는 데이터 중에서 가장 일반적인 것이라면 MFC 클래스의 계층구조가 되겠네요. 이제 코드를 입력해 보죠.

 샘플 프로젝트입니다.

1) 다이얼로그 베이스의 프로젝트를 하나 만듭니다. 그리고는 우선 OnInitDialog() 함수에 손을 대어 봅니다. 클래스 위저드에서 WM_INITDIALOG 메시지를 오버라이드 하면 되죠.

  트리컨트롤 아래에 선택된 내용을 표시하려 하는데, 처음 실행되면서 특정 내용을 나타내기 위해, CDialog 클래스의 OnInitDialog() 함수를 호출하기 전에    

    m_Label = CString("선택된 항목 : ");

 를 실행시켜 주어야 제대로 나타납니다. OnInitDialog() 함수 다음에 실행했더니 제대로 나타나질 않더군요.

 다음은 입력된 코드입니다.

 

// 노드로 추가될 텍스트들
char *pLevel1[] = {"CObject"};
char *pLevel2[] = {"CWnd", "CCmdTarget"};
char *pLevel31[] = {"CFrameWnd", "CView", "CDialog"};
char *pLevel32[] = {"CWinApp", "CDocument", "CDocTemplate"};

BOOL CTreeDlg::OnInitDialog()
{
        m_Label = CString("선택된 항목 : ");  // 처음 실행되면서 표시되는 내용

        CDialog::OnInitDialog();
        ......................................

       // TODO: Add extra initialization here


        // 트리컨트롤에 이미지 리스트 추가
        m_ImageTree.Create(IDB_TREE, 16, 2, RGB(0,128,128));
        m_ctrlTree.SetImageList(&m_ImageTree, TVSIL_NORMAL);

        TV_INSERTSTRUCT tvinsert;

        // 옵션설정
        tvinsert.hParent = NULL;
        tvinsert.hInsertAfter = TVI_LAST;
        tvinsert.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
        tvinsert.item.state = 0;
        tvinsert.item.stateMask = 0;
        tvinsert.item.cchTextMax = 60;
        tvinsert.item.iSelectedImage = 1;
        tvinsert.item.cChildren = 0;

        // 레벨1의 노드 추가
        tvinsert.item.pszText = pLevel1[0];
        tvinsert.item.iImage = 0;
        HTREEITEM hRoot = m_ctrlTree.InsertItem(&tvinsert);
        HTREEITEM hItem;

        // 레벨2의 노드 추가
        tvinsert.hParent = hRoot;  // 레벨1의 자식으로 추가
        tvinsert.item.pszText = pLevel2[0];
        hItem = m_ctrlTree.InsertItem(&tvinsert);

        // 레벨3의 노드 추가
        tvinsert.hParent = hItem;  // 레벨2의 자식으로 추가
        for(int i=0; i<3; i++) {
                tvinsert.item.pszText = pLevel31[i];
                m_ctrlTree.InsertItem(&tvinsert);
        }

        m_ctrlTree.Expand(hItem, TVE_EXPAND);

        // 레벨2의 노드 추가
        tvinsert.hParent = hRoot;  // 레벨1의 자식으로 추가
        tvinsert.item.pszText = pLevel2[1];
        tvinsert.item.iImage = 0;
        hItem = m_ctrlTree.InsertItem(&tvinsert);

        // 레벨3의 노드추가
        tvinsert.hParent = hItem;  // 레벨2의 자식으로 추가
        for(i=0; i<3; i++) {
                tvinsert.item.pszText = pLevel32[i];
                m_ctrlTree.InsertItem(&tvinsert);
        }

        m_ctrlTree.Expand(hItem, TVE_EXPAND);   
        m_ctrlTree.Expand(hRoot, TVE_EXPAND);

        return TRUE;  // return TRUE  unless you set the focus to a control
}

 

2) 다이얼로그 템플릿은 다음과 같이 배치합니다. 트리 컨트롤을 놓고, 그 아래에 Static 컨트롤을 놓습니다.

 

3) 트리 컨트롤을 제어하기 위해 CTreeCtrl형의 Control형 멤버변수 m_ctrlTree와 연결합니다. 방법은 ClassWizard를 실행시켜서 Member Variables 탭에서 입력하면 됩니다.

 그리고, 트리 컨트롤의 노드에 아이콘을 넣어주기 위해 CImageList형의 변수 m_ImageTree 를 추가합니다.

 세 번째로, 트리 컨트롤에서 선택된 문자열을 표시해 주기 위해 Static 컨트롤과 연결될 m_Label 변수를 정의합니다. 역시 클래스 위저드를 실행시켜서 Member Variables 탭에서 다음과 같이 입력하는 겁니다.

 Control IDs : IDC_LABEL          Type : CString          Member : m_Label

 

4) OnInitDialog() 함수부분만 처리해주면 트리컨트롤의 모양만 나타날 뿐입니다. 이 컨트롤의 작동에 대해 무언가 반응을 하려면 어딘가 처리를 해주어야 하겠죠.

 여기서는 트리컨트롤에서 선택한 항목을 레이블에 표시해주기로 합니다. 그러기 위해서는 클래스 위저드에서 TVN_SELCHANGE 메시지를 처리해줍니다. 이 메시지에 대한 핸들러는 다음과 같습니다.

 

void CTreeDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
        NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
       // TODO: Add your control notification handler code here

        HTREEITEM hItem = pNMTreeView->itemNew.hItem;

        char text[20];
        TV_ITEM item;
        memset(text, 0, 20);

        item.mask = TVIF_HANDLE | TVIF_TEXT;
        item.hItem = hItem;  // 새로 선택된 노드의 정보를 얻고자
        item.pszText = text;
        item.cchTextMax = 30;
        m_ctrlTree.GetItem(&item);

        m_Label = "선택된 항목 : " + CString(text);
        UpdateData(FALSE);

        *pResult = 0;
}

 

5) 그리고 트리 컨트롤의 속성을 다음과 같이 지정합니다.

각 속성들과 그 의미는 다음과 같습니다.

Has buttons : 하위 노드가 있는 노드에 사각형 모양의 버튼을 그려줍니다. 노드가 확장되어 있을 때 - 모양, 축소되어 있을 때 + 모양이 되는 사각형의 조그만 버튼 말이죠.

Has lines : 각 노드를 연결하는 라인을 그려줍니다.

Lines at root : 루트 노드에도 라인을 그려줍니다.

Edit labels : 레이블을 편집할 수 있도록 합니다.

Disable drag drop : 드래그 앤 드롭을 할 수 없도록 합니다.

Border : 말 그대로 트리 컨트롤 주위의 테두리 라인을 그려주거나 없애줍니다.

 

- the end of this article -