메뉴 닫기

MFC CTreeCtrl 완전 정복 – 계층 구조 UI를 구현하는 가장 쉬운 방법


MFC CTreeCtrl 완전 정복 – 계층 구조 UI를 구현하는 가장 쉬운 방법

🌲 C++ 윈도우 애플리케이션에서 트리 구조 UI가 필요하다면 CTreeCtrl을 주목하세요!

윈도우 애플리케이션을 개발하다 보면 폴더 구조나 계층적인 데이터를 시각적으로 표현해야 할 일이 자주 생깁니다.
그럴 때 유용하게 활용할 수 있는 것이 바로 MFC의 CTreeCtrl 클래스인데요.
처음 접할 땐 다소 낯설고 복잡해 보일 수 있지만, 정확한 구조와 기능을 이해하고 나면 오히려 UI 구현이 훨씬 수월해집니다.
이번 글에서는 CTreeCtrl이 어떤 클래스인지, 어떤 기능을 제공하는지부터 시작해 실제로 어떻게 노드를 추가하고 펼치거나 접는지까지 초보자도 따라 할 수 있게 단계별로 정리해드릴게요.
지금부터 함께 살펴보면서 트리 컨트롤의 기본부터 실전 활용까지 확실히 익혀보세요.

CTreeCtrl은 윈도우에서 계층적인 데이터를 트리 형태로 보여주는 컨트롤로, 각 노드는 HTREEITEM 객체를 통해 제어됩니다.
노드의 추가, 삭제, 이동, 펼침 및 접기 등 다양한 동작이 가능하며, 파일 탐색기 같은 인터페이스를 구현할 때 필수적으로 활용됩니다.
MFC 기반 애플리케이션을 제작 중이라면 꼭 알아야 할 핵심 요소라 할 수 있죠.
이번 글에서는 CTreeCtrl의 기초부터 실전 예제까지 모두 다뤄보겠습니다.







🌲 CTreeCtrl이란?

CTreeCtrl은 Microsoft Foundation Class (MFC) 라이브러리에서 제공하는 클래스 중 하나로, 윈도우 애플리케이션에서 계층 구조의 데이터를 트리 형태로 표현할 수 있도록 도와주는 컨트롤입니다.
Windows의 Tree View 컨트롤을 감싸고 있는 MFC 래퍼 클래스라고 볼 수 있으며, 사용자가 폴더처럼 펼치고 접을 수 있는 UI를 쉽게 구현할 수 있도록 설계되어 있습니다.

  • 🌳계층형 데이터 표시를 위한 트리 구조 제공
  • 📌HTREEITEM 객체를 통해 노드 제어
  • 📂노드의 추가, 삭제, 수정, 이동, 펼침/접기 지원
  • 🖥️파일 탐색기처럼 시각적 탐색이 필요한 UI 구현에 최적

초보 개발자라면 처음엔 다소 생소할 수 있지만, 한 번 구조를 이해하고 나면 다양한 트리 기반 인터페이스를 구현할 수 있는 강력한 도구가 됩니다.
특히 노드 간 계층 구조를 시각적으로 표현할 때 다른 컨트롤보다 훨씬 직관적이고 효율적인 것이 장점입니다.


🔧 기본 구조와 주요 멤버 함수

CTreeCtrl을 제대로 활용하려면 이 클래스가 어떻게 구성되어 있는지를 먼저 이해해야 합니다.
이 컨트롤은 기본적으로 CWnd를 상속한 윈도우 컨트롤로, 트리 형태의 데이터를 노드 단위로 다루며 다양한 멤버 함수를 제공합니다.
여기서 핵심이 되는 개념은 HTREEITEM이라는 핸들을 통해 각 노드를 식별하고, 그 노드를 기반으로 작업을 수행한다는 점입니다.

또한 트리 컨트롤은 각 노드에 텍스트, 아이콘, 이미지 등을 지정할 수 있으며, 노드 간의 부모-자식 관계도 자유롭게 설정할 수 있습니다.
이를 통해 복잡한 계층 구조도 시각적으로 매우 명확하게 표현할 수 있죠.

  • 📌InsertItem : 새 노드를 추가할 때 사용
  • DeleteItem : 특정 노드를 제거
  • 📂Expand : 노드를 펼치거나 접는 데 사용
  • 🔍GetChildItem, GetNextSiblingItem 등으로 노드 탐색

CODE BLOCK
// 트리 컨트롤에서 아이템 추가 예시
HTREEITEM hRoot = m_TreeCtrl.InsertItem(_T("루트 노드"));
HTREEITEM hChild = m_TreeCtrl.InsertItem(_T("자식 노드"), hRoot);
m_TreeCtrl.Expand(hRoot, TVE_EXPAND);

위와 같은 함수들을 적절히 조합하면, 매우 직관적인 방식으로 트리 형태의 데이터를 제어할 수 있습니다.
트리 컨트롤을 잘만 다루면 사용자에게 깔끔하고 논리적인 UI 흐름을 제공할 수 있어, 특히 대규모 설정 화면이나 프로젝트 구조를 구성할 때 큰 장점을 가집니다.







노드 추가 및 삭제 방법

CTreeCtrl을 활용할 때 가장 기본적이면서도 자주 사용되는 기능이 바로 노드 추가와 삭제입니다.
사용자가 직접 트리 구조를 편집하거나 프로그램적으로 동적으로 구조를 구성할 수 있게 하기 위해서는, 이 기능에 대한 이해가 꼭 필요합니다.

노드를 추가할 때는 InsertItem 함수를 사용하며, 이 함수는 노드 텍스트, 부모 노드, 이미지 등 다양한 파라미터를 설정할 수 있습니다.
삭제는 DeleteItem 또는 전체 삭제를 위한 DeleteAllItems를 사용하게 됩니다.

  • 🆕InsertItem으로 노드 생성 및 삽입
  • 🗑️DeleteItem으로 특정 노드 삭제
  • 🧹DeleteAllItems로 전체 초기화

CODE BLOCK
// 노드 추가
HTREEITEM hRoot = m_TreeCtrl.InsertItem(_T("루트"));
HTREEITEM hChild = m_TreeCtrl.InsertItem(_T("하위 노드"), hRoot);

// 노드 삭제
m_TreeCtrl.DeleteItem(hChild);

// 전체 노드 삭제
m_TreeCtrl.DeleteAllItems();

이처럼 간단한 API 호출만으로도 트리 구조의 노드를 동적으로 생성하고 삭제할 수 있어, 사용자 맞춤형 인터페이스를 구성하는 데 매우 유용합니다.
또한 삭제할 때에는 부모-자식 관계를 잘 파악하여 필요 없는 노드만 선택적으로 제거하는 로직도 함께 고려해야 합니다.


📂 노드 펼치기/접기 제어

트리 컨트롤의 핵심 기능 중 하나는 사용자가 노드를 자유롭게 펼치고 접을 수 있다는 점입니다.
이러한 상호작용은 정보의 계층 구조를 명확히 보여주고, 필요할 때만 하위 항목을 볼 수 있도록 하여 UI의 가독성과 효율성을 높이는 데 큰 기여를 합니다.

MFC의 CTreeCtrl에서는 이 기능을 Expand() 함수를 통해 제어할 수 있으며, 원하는 노드를 명시적으로 확장하거나 접는 작업이 가능합니다.
예를 들어 설정 화면을 초기화할 때 루트 노드만 열어두고 나머지는 닫아둘 수 있고, 특정 상황에서 자동으로 펼쳐지도록 설정할 수도 있습니다.

  • 🔼TVE_EXPAND : 노드를 펼치는 상수
  • 🔽TVE_COLLAPSE : 노드를 접는 상수
  • 🔁TVE_TOGGLE : 펼침/접기 전환

CODE BLOCK
// 특정 노드 펼치기
m_TreeCtrl.Expand(hRoot, TVE_EXPAND);

// 특정 노드 접기
m_TreeCtrl.Expand(hRoot, TVE_COLLAPSE);

// 현재 상태에 따라 자동 전환
m_TreeCtrl.Expand(hRoot, TVE_TOGGLE);

이러한 제어는 사용자 경험을 유연하게 만들 뿐만 아니라, UI 초기화 및 상태 복원에도 자주 사용됩니다.
예를 들어 사용자가 마지막에 열어둔 노드를 저장해두고, 다시 프로그램을 실행했을 때 해당 노드를 자동으로 펼쳐주는 것도 가능합니다.







💡 실전 예제 코드로 이해하기

지금까지 CTreeCtrl의 구조와 주요 기능에 대해 알아봤다면, 이제는 실제 예제 코드를 통해 개념을 더욱 확실히 이해해보는 것이 좋습니다.
이 섹션에서는 노드 추가부터 펼치기, 삭제까지 전체 흐름을 코드로 구현한 예제를 소개합니다.
이 예제는 MFC 애플리케이션의 OnInitDialog 함수나 OnCreate 함수 등에서 사용할 수 있으며, 트리 컨트롤 초기화의 기초 틀로 매우 유용하게 활용됩니다.

CODE BLOCK
void CMyDialog::InitTreeControl()
{
    // 트리 컨트롤 초기화
    m_TreeCtrl.DeleteAllItems();

    // 루트 노드 추가
    HTREEITEM hRoot = m_TreeCtrl.InsertItem(_T("회사"));

    // 자식 노드 추가
    HTREEITEM hDept1 = m_TreeCtrl.InsertItem(_T("개발부서"), hRoot);
    HTREEITEM hDept2 = m_TreeCtrl.InsertItem(_T("디자인부서"), hRoot);

    // 하위 자식 노드 추가
    m_TreeCtrl.InsertItem(_T("프론트엔드 팀"), hDept1);
    m_TreeCtrl.InsertItem(_T("백엔드 팀"), hDept1);

    // 노드 펼치기
    m_TreeCtrl.Expand(hRoot, TVE_EXPAND);
    m_TreeCtrl.Expand(hDept1, TVE_EXPAND);
}

위 코드처럼 트리 구조를 구성하면, 사용자는 회사 → 부서 → 팀 순으로 명확한 계층 구조를 탐색할 수 있게 됩니다.
이 구조는 직관적인 UI 제공은 물론, 코드 구조 자체도 명확하게 설계할 수 있어 유지 보수에 있어서도 매우 유리합니다.

💎 핵심 포인트:
CTreeCtrl은 복잡한 구조를 시각적으로 단순하게 보여주기 때문에, 사용자가 보다 쉽게 정보를 인식하고 탐색할 수 있는 인터페이스를 구현할 수 있습니다.

이제 여러분도 트리 컨트롤을 활용해 원하는 구조의 UI를 설계할 수 있을 것입니다.
이제 다음 단계로는 이벤트 처리, 커스텀 이미지 삽입, 노드 선택 제어 등 더 고급 기능도 도전해볼 수 있습니다.


자주 묻는 질문 (FAQ)

CTreeCtrl은 어떤 상황에서 사용하는 게 좋을까요?
계층 구조의 데이터를 시각적으로 표현해야 할 때 적합합니다. 예를 들어 파일 탐색기, 설정 메뉴, 조직도, 카테고리 트리 등에서 매우 유용합니다.
HTREEITEM은 무엇을 의미하나요?
HTREEITEM은 트리 컨트롤 내의 특정 노드를 식별하기 위한 핸들입니다. 각 노드는 고유한 HTREEITEM으로 참조되며, 이를 통해 위치나 상태를 제어할 수 있습니다.
노드에 이미지를 추가할 수 있나요?
가능합니다. 이미지 리스트를 설정한 뒤 각 노드에 아이콘 인덱스를 지정하면 원하는 아이콘을 트리 항목에 표시할 수 있습니다.
트리 노드를 드래그 앤 드롭으로 이동시킬 수 있나요?
네, 마우스 이벤트를 처리하고 적절한 메시지를 구현하면 노드를 드래그하여 다른 위치로 이동하는 기능도 구현 가능합니다.
노드를 클릭했을 때 이벤트를 처리하려면 어떻게 하나요?
NM_CLICK 또는 TVN_SELCHANGED 같은 트리 컨트롤 관련 메시지를 핸들링하여 사용자가 노드를 클릭하거나 선택했을 때 동작을 지정할 수 있습니다.
트리 구조를 저장하고 다시 불러오는 방법은?
각 노드의 구조를 재귀적으로 순회하며 텍스트와 계층 정보를 저장한 후, 이를 기반으로 나중에 트리를 재구성할 수 있습니다. 파일이나 데이터베이스에 저장하는 방식이 일반적입니다.
InsertItem은 어디에 삽입되는 건가요?
InsertItem 함수는 부모 노드를 지정해 자식으로 삽입할 수 있으며, 부모를 지정하지 않으면 최상위 루트 노드로 간주됩니다.
트리 컨트롤에서 특정 노드를 찾는 방법은?
GetChildItem, GetNextSiblingItem, GetParentItem 등을 활용해 노드를 탐색할 수 있습니다. 반복문 또는 재귀 방식으로 원하는 노드를 찾는 것이 일반적입니다.



🧭 MFC CTreeCtrl로 계층형 UI 완벽 구현하기

이번 글에서는 MFC 애플리케이션 개발에서 자주 활용되는 CTreeCtrl 컨트롤에 대해 단계별로 알아봤습니다.
트리 구조를 통해 계층형 데이터를 표현하고 사용자와의 인터페이스를 강화할 수 있는 강력한 도구인 CTreeCtrl은, 사용법을 정확히 익히면 파일 탐색기처럼 직관적인 UI를 구현할 수 있게 됩니다.
노드 추가, 삭제, 펼침 및 접기, 이벤트 처리까지 실제 코드 예제를 기반으로 설명했기 때문에 실무에서도 바로 활용할 수 있을 것입니다.
윈도우 기반 애플리케이션에서 구조적인 UI가 필요하다면, CTreeCtrl은 분명히 가장 신뢰할 수 있는 선택지가 될 수 있습니다.


🏷️ 관련 태그 : MFC, CTreeCtrl, 윈도우UI개발, 계층구조, 트리컨트롤, HTREEITEM, C++, UI프로그래밍, 트리구조, InsertItem, 윈도우클래스