CAFE

[22기 이도현] TreeView 기술문서

작성자22기 이도현|작성시간11.08.22|조회수538 목록 댓글 0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

TREE VIEW

- LEE DO HYEON

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

이 도 현

 

    

 

 

1

트리뷰란?

 

1

 

2

STYLE

 

1

 

3

메시지

 

2

 

4

통지 메시지

 

4

 

5

TVINSERTSTRUCT

 

5

 

6

흐름

 

6

 

7

예제

 

7

 

 


 

 

 

1.    About Tree View

 

Tree View 컨트롤은 계층적인 구조를 가지는 자료를 표시(View)하는 컨트롤을 말한다.

왼쪽에 있는 디렉토리 트리가 대표적인 예다.
사용자의 하드 디스크의 모든 서브 디렉토리와 네트워크 자원까지

한눈에 체계적으로 보여준다.

트리를 구성하는 각 항목을 노드라고 하며 텍스트를 나타내는 레이블과 항목의 종류를 나타내는 비트맵으로 구성되어있다.

항목을 더블 클릭하거나 항목 옆의 +,- 버튼을 눌러 세부항목을 확장하거나 축소할 수 있다.

 

2.    Style

-      TVS_HASBUTTONS
자식 항목을 가진 부모 항목 옆에 +, - 버튼을 표시한다.
+
버튼을 누르면 항목이 확장되어 자식 항목이 펼쳐지며, - 버튼을 누르면 항목이 축소된다.

 

-      TVS_HASBUTTONS
항목간의 계층구조를 좀더 명확히 보이기 위해 점선으로 항목간을 연결하여 표시한다.

 

-      TVS_LINESATROOT
사용자가 항목의 텍스트를 직접 수정할 수 있도록 한다.

 

-      TVS_DISABLEDRAGDROP
스타일의 이름대로 항목을 드래그를 하지 못하게 한다.
이 스타일이 설정되면 TVN_BEGINDRAG 통지 메시지가 전달되지 않는다.

 

-      TVS_SHOWSELALWAYS
트리뷰가 포커스를 가지지 않은 상태에서도 선택된 항목이 반전된 상태로 남는다.

 

 

 

-      TVS_TRACKSELECT
한 번 클릭으로 항목을 선택함과 동시에 확장하며, 비 선택된 항목은 자동 축소한다.

 

-      TVS_CHECKBOXES
항목 옆에 체크 박스를 보여준다. 상태 이미지 0은 체크된 모양, 1은 체크되지 않은 모양이다.

 

 

3.    메시지

 

-      TVM_CREATEDRAGIMAGE
이미지 리스트를 만들고 lParam 으로 지정한 항목의 드래그 비트맵을 만들어 이미지 리스트에 포함시킨다
.
리턴 값은 이미지 리스트의 핸들이다.

-      TVM_DELETEITEM
lParam으로 지정한 항목을 삭제한다
.
lParam
TVI_ROOT면 트리의 모든 항목이 삭제된다.

-      TVM_EDITLABEL
lParam으로 지정한 항목을 즉시 편집한다
.
이 메시지 후에 곧바로 TVN_BEGINLABELEDIT 통지 메시지가 전달된다.

-      TVM_ENDEDITLABELNOW
편집중인 항목 편집을 중단한다. wParam TRUE이면 편집동작은 취소되며, FALSE면 편집동작 저장 후 종료한다.

-      TVM_EXPAND
lParam으로 전달된 항목을 확장하거나 축소한다
.
이때 wParam은 다음 중 하나의 플래그가 된다
.
  TVE_COLLAPSE: 축소한다
.
 → TVE_COLLAPSERESET:
축소함과 동시에 차일드를 파괴한다.
 → TVE_EXPAND:
확장한다
.
 → TVE_TOGGLE:
확장되어 있으면 축소하고 축소되어 있으면 확장한다.

-      TVM_GETCOUNT
항목의 개수를 구한다.(총 노드의 개수)

-      TVM_GETEDITCONTROL
항목 편집에 사용되는 에디트 컨트롤의 핸들을 구한다.

-      TVM_GETINDENT
인덴트 값을 구한다.

-      TVM_GETIMAGELIST
트리 컨트롤과 연결된 이미지 리스트의 핸들을 구한다
.
wParam
은 구하고자 하는 이미지 리스트의 종류를 지정한다
.
TVSIL_NORMAL, TVSIL_STATE
중 하나이다.

-      TVM_GETISEARCHSTRING
사용자가 키보드로 원하는 항목을 찾아갈 때 사용하는 점진적 검색 문자열을 구한다
.
lParam
으로 리턴값을 돌려받기 위한 버퍼의 포인터를 넘겨준다.

-      TVM_GETITEM
특정 항목을 찾는다. 찾고자 하는 항목의 정보를 TVITEM 구조체의 hItem 멤버에 대입한 후

이 구조체를 lParam으로 넘기면 구조체에 항목의 정보를 채워준다.
이때 채워지는 정보는 mask 멤버가 지정하는 값에 한해서 채워진다.

-      TVM_GETTIEMRECT
항목이 차지하고 있는 사각영역을 구한다
.
lParam
으로 RECT 구조체를 넘기면 이 구조체에 사각영역을 채운다
.
wParam
TRUE이면 문자열 영역에 대해서만 사각영역이 구해지며, FALSE이면 선을 포함한 영역까지 다 구한다
.
항목이 보이면 TRUE를 리턴하며, 아닐 시 FALSE를 리턴한다.

-      TVM_GETNEXTTIEM
보이는 항목의 개수를 구한다
.
, 이 개수는 트리 컨트롤의 높이를 단순히 항목 높이로 나눈 것이므로 실제로 리턴되는

값은 층 항목보다 작을 수도 있다.

-      TVM_HITTEST
특정한 한 점이 트리 컨트롤의 어디쯤인가를 조사한다.

-      TVM_INSERTITEM
lParam으로 전달되는 TV_INSERTSTRUCT 구조체의 정보를 참조하여 항목을 추가한다.

-      TVM_SELECTITEM
lParam으로 지정한 항목을 선택하거나 보이게 하거나 드롭 타겟으로 그린다.

-      TVM_SETIMAGELIST
트리 컨트롤과 연결될 이미지 리스트를 지정한다
.
lParam
으로 이미지 리스트의 핸들을 주며 wParam으로 이미지 리스트의 종류를 지정한다.

-      TVM_SETINDENT
자식 항목과 부모 항목의 가로 좌표 차이인 인덴트 값을 wParam으로 지정한다.

-      TVM_SETITEM
항목의 속성을 설정한다. TVITEM 구조체를 작성한 후 lParam으로 전달 한다
.

-      TVM_SORTCHILDREN
lParam으로 지정한 항목의 자식 항목들을 정렬한다
.
wParam
을 반드시 0(NULL)을 주어야 한다.

-      TVM_SORTCHILDRENCB
프로그램이 정의한 콜백 함수를 사용하여 트리의 항목들을 정렬한다
.
lParam
으로 TV_SORTCB 구조체를 전달한다.

 

4.    통지 메시지

-      TVN_BEGINDRAG
왼쪽 마우스 버튼으로 항목을 드래그하기 시작할 때 발생한다.

-      TVN_BEGINLABELEDIT
레이블을 편집할 때 발생한다.

-      TVN_DELETEITEM
한 항목이 삭제될 때 발생한다.

-      TVN_ENDLABELEDIT
레이블 편집이 완료되었을 때 발생한다.

-      TVN_GETDISPINFO
항목의 출력이나 정렬을 위한 정보를 부모 윈도우에게 요청한다.

-      TVN_ITEMEXPANDED
트리가 확장 또는 축소되었을 때 발생한다.

-      TVN_ITEMEXPANDING
트리가 확장 또는 축소되고 있을 때 발생한다.

-      TVN_KEYDOWN
트리 컨트롤이 포커스를 가지고 있는 상태에서 키보드 입력이 되었을 때 발생한다.

-      TVN_SELCHANGED
사용자가 다른 항목을 선택했을 때 발생한다.

-      TVN_SELCHANGING
사용자가 다른 항목을 선택하려고 할 때 발생한다.

-      TVN_SETDISPINFO

부모 윈도우가 정렬이나 출력을 위해 유지하고 있는 항목의 정보가 갱신되어야 함을
알린다.


 

 

5.    TVINSERTSTRUCT 구조체

TVINSERTSTRUCT 구조체는 항목을 추가할 때 TVN_INSERTITEM 메시지를
보내는데 이 메시지의 lParam으로 추가하고자 하는 항목의 위치와 속성들을
가지는 TVINSERTSTRUCT 구조체의 포인터를 전달한다.
원형은 아래와 같다
.
  typedef struct tag TVINSERTSTRUCT
  {

     HTREEITEM hParent; //
트리의 부모 핸들값. ROOT라면 NULL
     HTREEITEM hInsertAfter //추가될 항목은 어느 방식으로 추가될지 결정한다.
     TVITEMEX  itemex; //실제 추가되는 항목에 대한 정보를 가지는 TVITEM or TVITEMEX 구조체
  }TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;

 

hInsertAfter에 올수 있는 인자 3가지

-       TVI_FIRST : 제일 첫 위치에 삽입한다.

-       TVI_SORT : 알파벳 순으로 정렬한 위치에 삽입한다.

-       TVI_LAST : 제일 마지막 위치에 삽입한다.

 

-      TVITEM / TVITEMEX 구조체

typedef struct tag TVITEMEX

{

UINT mask;

HTREEITEM hItem;

UINT state;

UINT stateMask;

LPSTR psztext;

int cchTextMax;

int iImage;

int iSelectedImage;

int cchildren;

LPARAM lParam;

int iIntegral;
} TVITEMEX, FAR *LPTVITEMEX;

 

-       mask
TVITEMEX
구조체의 멤버 중 어느 멤버가 유효한 값을 가지는지 확인한다.

-       state, stateMask
state는 항목의 현재 상태를 지정하며 stateMask는 어떤 상태가 가능한가를 지정한다.

-       pszText
항목의 실제 내용이 되는 문자열이다.

-       cchTextMax
pszText의 길이를 지정한다.

-       iImage
항목의 왼쪽에 나타날 이미지의 번호를 지정하며, 이미지 리스트 내의 인덱스 값을 지정한다.

-       iSelectedImage
항목이 선택되었을 때 나타날 이미지의 번호를 지정하며, 이미지 리스트 내의 인덱스 값을 지정한다.

-       children
이 항목이 자식 항목을 가지고 있는지 조사한다
.
0
이면 자식항목이 없는 것이고, 1이면 하나 이상의 항목이 있다는 뜻이다.

 

 

6.    흐름


 

 

 

 

7.    예제

-      실습
그림과 같이 ROOT는 선문대학교 원화관이 있다.
그 상태에서 자식 노드를 삽입, 삭제 할 수 있는 프로그램을 만들어 보자.

 

<실습 완성 화면>

부가 설명은 코드에 있는 tvParam 구조체를 사용하여 lParam으로 값을
넘겨 사용한다.


 

 

-      코드 (TreeView.h)

#include <windows.h>

#include "resource.h"

#include <commctrl.h>

 

HWND hTree; //전역으로사용될TreeView의핸들값..

 

//TreeView lParam으로사용될부분이다.

struct tvParam{

        TCHAR tCaption[20]; //20글자까지저장한다.

};

//더많은정보를넣을수있지만그냥부가설명용으로20글자만넘긴다.

//꼭구조체로선언할필요는전혀없다.

//만들기편하도록임의적으로틀을만드는것이좋다.

 

BOOL CALLBACK DlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam);

 

void ExitProc(HWND hDlg);

void OnNotify(HWND hDlg,LPNMHDR hdr,LPNMTREEVIEW ntv);

void OnInit(HWND hDlg);

void OnCommand(HWND hDlg, WORD cid);

 

void Change_TreeViewItem(HWND hDlg,LPNMTREEVIEW ntv); //트리뷰의아이템이바뀌었을때

void Add_TreeViewItem(HWND hDlg); //트리뷰아이템추가

void Delete_TreeViewItem(HWND hDlg); //트리뷰해당아이템삭제

 


 

 

-      코드 (TreeView.cpp)

#include "TreeView.h"

 

void Add_TreeViewItem(HWND hDlg)

{

        TCHAR cTitle[20]; //이름

        TCHAR cCaption[20]; //부가설명

        GetDlgItemText(hDlg,IDC_NAME,cTitle,20);

        SetDlgItemText(hDlg,IDC_NAME,TEXT(""));

        GetDlgItemText(hDlg,IDC_CAPTION,cCaption,20);

        SetDlgItemText(hDlg,IDC_CAPTION,TEXT(""));

       

        HTREEITEM hNow; //현재TreeView내의선택된위치

        TVINSERTSTRUCT TI; //TreeView 구조체선언

        tvParam *tParam = new tvParam; //lParam으로넘길구조체생성

 

        lstrcpy(tParam->tCaption,cCaption); //가져온정보를사용자정의구조체에넣는다.

        hNow = TreeView_GetSelection(hTree);

        TI.hParent = hNow; //부모가될현재객체를얻어옵니다.

        TI.hInsertAfter = TVI_LAST;

        TI.item.pszText = cTitle;

        TI.item.mask = TVIF_TEXT | TVIF_PARAM;//mask에는사용될속성을정의합니다.

 

        //lParam에는tParam을넘겨줘야한다.

        TI.item.lParam = (LPARAM)tParam; //형변환으로넘겨주기.

        //이제구조체정보를입력했으므로, 실질적추가를해줍니다.

        TreeView_InsertItem(hTree,&TI);

        //추가를한후에부모노드를확장하여추가한결과를표시해줍니다..

        TreeView_Expand(hTree,hNow,TVE_EXPAND);

}

 

void Change_TreeViewItem(HWND hDlg,LPNMTREEVIEW ntv)

{

        TVITEM Ti; //항목에대한정보를갖을TVITEM을선언.

        tvParam *tParam; //lParam으로넘어올정보

        TCHAR cTitle[20]; //pszText에대입될정보

 

        Ti.mask = TVIF_TEXT | TVIF_PARAM;

        Ti.hItem = ntv->itemNew.hItem; //넘어온ntv의정보를통하여아이템을얻어옴

        Ti.pszText = cTitle;

        Ti.cchTextMax = 20;

 

                      TreeView_GetItem(hTree,&Ti); //정보를가지고온다.

        tParam = (tvParam*)Ti.lParam; //tParam에가져온lParam정보를대입한다.

 

        //SetDlgItemText를통하여IDC_NODEIDC_INFO를갱신한다.

        SetDlgItemText(hDlg,IDC_NODE,cTitle);

        SetDlgItemText(hDlg,IDC_INFO,tParam->tCaption);

       

}

 

void Delete_TreeViewItem(HWND hDlg)

{

        HTREEITEM hNow; //현재TreeView내의선택된위치

        //현재클릭된정보를가져온다. hNow에정보저장.

        hNow = TreeView_GetSelection(hTree);

        if(hNow == TreeView_GetRoot(hTree)){ //루트일경우삭제하지않는다.

                  MessageBox(hDlg,TEXT("루트는삭제불가!"),TEXT("경고임ㅎ"),MB_OK);

                  return;

        }

        //삭제'_';

        TreeView_DeleteItem(hTree,hNow);

}

 

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShowCmd)

{

        DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), 0, DlgProc);

        return 0;

}

 

BOOL CALLBACK DlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

        switch(iMessage)

        {

        case WM_INITDIALOG:     OnInit(hDlg); return TRUE;

        case WM_COMMAND:     OnCommand(hDlg, LOWORD(wParam)); return TRUE;

        case WM_NOTIFY:

OnNotify(hDlg,(LPNMHDR)lParam,(LPNMTREEVIEW)lParam); return TRUE;

        }

        return FALSE;

}

 

void OnNotify(HWND hDlg,LPNMHDR hdr,LPNMTREEVIEW ntv)

{

        if(hdr->hwndFrom == GetDlgItem(hDlg,IDC_TREE1))

        {

                  if(hdr->code == TVN_SELCHANGED)

//TVN_SELCHANGED : 사용자가다른항목을선택했을때발생.

                  {

                             Change_TreeViewItem(hDlg,ntv);

                  }

        }

}

 

void OnInit(HWND hDlg)

{      

        //최초의부모노드를만들어주기로한다.....

        hTree = GetDlgItem(hDlg, IDC_TREE1);

        TCHAR cTitle[20] = TEXT("선문대학교원화관");

        TCHAR cCaption[20] = TEXT("부가설명이지요");

       

        TVINSERTSTRUCT TI; //트리뷰구조체를사용한다.

        tvParam *tParam = new tvParam; //lParam에 넘길 부가설명을 담당할 구조체

       

        TI.hParent = NULL; //부모는부모가없음.

        TI.hInsertAfter=TVI_LAST; //마지막에넣던첫번째에넣던상관없다. 인자아무거나..

        TI.item.mask=TVIF_TEXT |TVIF_PARAM; // 아이템과파람만넘기도록한다.

        TI.item.pszText = cTitle; // 값을넘기고..

 

        lstrcpy(tParam->tCaption,cCaption);

        TI.item.lParam = (LPARAM)tParam;

        TreeView_InsertItem(hTree,&TI);

        TreeView_Expand(hTree,NULL,TVE_EXPAND);

 

        SetDlgItemText(hDlg,IDC_NODE,cTitle);

        TreeView_Select(hTree,TreeView_GetRoot(hTree),TVGN_CARET); //강제로Root를선택

}

 

void OnCommand(HWND hDlg, WORD cid)

{

        switch(cid)

        {

        case IDCANCEL:  ExitProc(hDlg);                         break;

        case ID_OK:       Add_TreeViewItem(hDlg); break;

        case ID_DEL: Delete_TreeViewItem(hDlg); break;

        }

}

 

void ExitProc(HWND hDlg)

{

        EndDialog(hDlg, 0);

}

 

 

-      간략학 코드 설명

첫 실행시(Dialog Init, ROOT로 선문대학교원화관 노드를 생성합니다.
TreeView
안의 Node를 클릭 시 현재 Node Title lParam에 들어있는 tvParam

불러와서 부가설명에 들어있는 내용을 Static Text Window에 출력합니다.
추가를 하게 되면
Add_TreeViewItem() 함수를 이용하여 TreeView안의 현재 선택된 아이템의
정보를 불러와 그 아이템을 부모로 지정하여 삽입하게 됩니다.
통지 메시지는 WM_NOTIFY로 전달되며, 노드가 선택되면 TVN_SELCHANGED 통지 메시지를

사용하여 선택된 노드의 정보를 가져옵니다.
삭제를 하게 되면 TreeView안의 현재 선택된 아이템을 삭제하게 됩니다
.
삭제되는 아이템의 자식들 또한 같이 삭제됩니다.

 

 

첨부파일 Tree_View기술문서(이도현).docx

다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
맨위로

카페 검색

카페 검색어 입력폼