출처 : http://maluchi.cafe24.com/xe/?mid=MyProgrammingTips&page=6&listStyle=list&document_srl=15989
[ 트리컨트롤(Tree Control) ]
1. 대화상자에 트리컨트롤을 붙이고 옵션을 다음과 같이 수정하자.
Edit labels: 트리컨트롤에서 에디트 기능을 사용할때.
Show selection always: 선택된 아이템을 표시할때.
2. 맴버 변수를 m_ctrTree라고 만들자(Control형 하나밖에 없다).
3. 아이템 추가하기
TVINSERTSTRUCT TI;
TI.hParent = TVI_ROOT; // TVI_ROOT, NULL
// HTREEITEM값을 사용하면 해당하는 아이템의 자식으로 아이템이 추가된다.
TI.hInsertAfter = TVI_LAST; // TVI_FIRST, TVI_LAST, TVI_SORT
TI.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TI.item.iImage = 0; // Tree가 선택안되었을때 표시될 아이콘
TI.item.iSelectedImage = 1; // Tree가 선택되었을때 표시될 아이콘
TI.item.pszText = "root";
HTREEITEM hTreeItem = m_ctrTree.InsertItem(&TI); // 추가된 아이템의 HTREEITEM이 리턴된다.
4. 아이템 확장하기.
m_ctrTree.Expand(hTreeItem, TVE_EXPAND);
5. 아이템 선택시 선택된 아이템 알아보기
+ TVN_SELCHANGED메시지를 사용한다.
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
HTREEITEM hTreeItem = pNMTreeView->itemNew.hItem; // 이 값이 선택된 아이템의 핸들이다.
6. 아이템 문자열 가져오기
CString str = m_ctrTree.GetItemText(hTreeItem);
7. 아이템 개수 알아내기
int nCount = m_ctrTree.GetCount();
8. 아이템 제거하기
m_ctrTree.DeleteItem(hTreeItem); // 핸들 아래단의 아이템들도 모두 제거된다.
9. 현재 선택된 아이템 알아내기
HTREEITEM hTreeItem = m_ctrTree.GetSelectedItem();
10. 위치로 아이템 찾기
CPoint p;
GetCursorPos(&p);
::ScreenToClient(m_ctrTree.m_hWnd, &p);
HTREEITEM hItem = m_ctrTree.HitTest(p);
11. 아이템 확장 축소 감지
+ TVN_ITEMEXPANDED메시지를 사용한다.
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
TVITEM item;
item.mask = TVIF_HANDLE;
item.hItem = pNMTreeView->itemNew.hItem;
m_ctrTree.GetItem(&item); // 아이템 정보를 알아낸다.
if(item.state & TVIS_EXPANDED)
{
// 확장
}
else
{
// 축소
}
12. 아이템 아이콘 설정 변경
m_ctrTree.SetItemImage(hTreeItem, 0, 1);
13. 아이템 에디트 입력중 포커스가 나갈때 입력중인 값 아이템에 적용하기
+ TVN_ENDLABELEDIT메시지를 사용한다.
TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
CEdit *pEdit = m_ctrTree.GetEditControl();
if(pEdit)
{
CString str;
pEdit->GetWindowText(str);
if(str.GetLength() > 0)
{
m_ctrTree.SetItemText(pTVDispInfo->item.hItem, str);
}
}
14. 이미지 리스트 설정
+ CImageList m_Image; // 32 x 16 아이콘 BITMAP 16 x 16 2개 짜리
m_Image.m_hImageList = ImageList_LoadImage(
(HINSTANCE) GetWindowLong(m_hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDB_BITMAP_SMALL), 16, 2,
RGB(255,255,255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
m_ctrTree.SetImageList(&m_Image, TVSIL_NORMAL);
- 드래그 앤 드롭 사용하기
1. 드래그 시작
- 트리컨트롤의 TVN_BEGINDRAG메시지 사용
CImageList *m_pTreeDragImage = NULL; // 드래그시 생성된 이미지 사용
HTREEITEM m_hDragItem = NULL; // 드래그시 처음 선택된 아이템 핸들 기억용
void CDlg::OnBegindragTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
// 드래그 이미지 생성
if(m_pTreeDragImage) m_pTreeDragImage->DeleteImageList();
m_pTreeDragImage = m_ctrTree.CreateDragImage(pNMTreeView->itemNew.hItem);
// 드래그시 사용할 이미지 크기 계산
RECT rc;
m_ctrTree.GetItemRect(pNMTreeView->itemNew.hItem, &rc, TRUE); // 아이콘을 포함하는 크기
// 드래그를 시작
m_pTreeDragImage->BeginDrag(0, CPoint(pNMTreeView->ptDrag.x-rc.left+16,
pNMTreeView->ptDrag.y-rc.top));
// 드래그 이미지 표시
m_pTreeDragImage->DragEnter(&m_ctrTree, pNMTreeView->ptDrag);
// 마우스 메시지를 잡아두고
SetCapture();
// 현재 선택된 아이템 핸들을 기억
m_hDragItem = pNMTreeView->itemNew.hItem;
*pResult = 0;
}
2. 이동
- WM_MOUSEMOVE메시지 사용
void CDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// 드래그 중이라면
if(m_pTreeDragImage)
{
// 트리컨트롤 기준으로 마우스 좌표 계산
CPoint p = point;
ClientToScreen(&p);
::ScreenToClient(m_ctrTree.m_hWnd, &p);
// 마우스가 위치한 아이템을 검사한다.항목이 트리 뷰 항목위에 있는지 확인하고 그렇다면 항목이 밝게 표시되도록한다.
HTREEITEM hItem = m_ctrTree.HitTest(p);
// 밝게 표시된 부분과 현재 선택된 아이템이 틀리다면
if(hItem != m_ctrTree.GetDropHilightItem())
{
// 드래그 이미지 그리기 중지
m_pTreeDragImage->DragLeave(&m_ctrTree);
// 새로운 항목을 밝게 표시한다.
m_ctrTree.SelectDropTarget(hItem);
// 드래그 이미지를 다시 보여준다.
m_pTreeDragImage->DragEnter(&m_ctrTree, p);
}
else
{
m_pTreeDragImage->DragMove(p);
}
}
CDialog::OnMouseMove(nFlags, point);
}
3. 드롭
- WM_LBUTTONUP메시지 사용
void CDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// 드래그 중이 었다면
if(m_pTreeDragImage)
{
// 마우스 메시지 캡쳐 기능을 제거한다.
ReleaseCapture();
// 드래그 과정을 중단한다.
m_pTreeDragImage->DragLeave(&m_ctrTree);
m_pTreeDragImage->EndDrag();
m_pTreeDragImage->DeleteImageList();
m_pTreeDragImage = NULL;
// 일단 마지막으로 밝게 표시되었던 항목을 찾는다.
HTREEITEM hTargetItem = m_ctrTree.GetDropHilightItem();
// 밝게 표시된 드롭 항목의 선택을 취소한다.
m_ctrTree.SelectDropTarget(NULL);
// 선택된 항목(아이템)이 있다면
if(hTargetItem)
{
// 선택된 아이템과 이동될 곳의 아이템이 같다면 이동할 필요가 없다.
if(m_hDragItem != hTargetItem)
{
// 현재 자식의 부모 아이템 핸들을 구한다.
HTREEITEM hParentItem = m_ctrTree.GetNextItem(m_hDragItem,
TVGN_PARENT);
// 이동하려는 곳이 자신이 직접속한 항목 이라면 이동할 필요가 없다.
if(hParentItem != hTargetItem)
{
// 트리의 내용을 이동하자.
MoveTreeItem(&m_ctrTree, m_hDragItem, hTargetItem);
// 이동된 곳의 트리를 확장하자.
m_ctrTree.Expand(hTargetItem, TVE_EXPAND);
// 이미지도 확장한걸로 바꾸자
m_ctrTree.SetItemImage(hTargetItem, 1, 1);
// 원본 트리의 모든 아이템이 사라졌다면 이미지 그림을 기본으로 바꾸자.
HTREEITEM hItem = m_ctrTree.GetChildItem(hParentItem);
if(!hItem)
{
m_ctrTree.SetItemImage(hParentItem, 0, 0);
}
}
}
}
m_hDragItem = NULL;
}
CDialog::OnLButtonUp(nFlags, point);
}
4. 트리 항목(아이템) 이동 함수
// 아이템 데이터 이동
BOOL MoveTreeItem(CTreeCtrl *pTree, HTREEITEM hSrcItem, HTREEITEM hDestItem)
{
// 이동할 아이템의 정보를 알아내자.
TVITEM TV;
char str[256];
ZeroMemory(str, sizeof(str));
TV.hItem = hSrcItem;
TV.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TV.pszText = str;
TV.cchTextMax = sizeof(str);
m_ctrTree.GetItem(&TV);
DWORD dwData = pTree->GetItemData(hSrcItem);
// 아이템을 추가 하자.
TVINSERTSTRUCT TI;
TI.hParent = hDestItem;
TI.hInsertAfter = TVI_LAST;
TI.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TI.item.iImage = TV.iImage;
TI.item.iSelectedImage = TV.iSelectedImage;
TI.item.pszText = TV.pszText;
HTREEITEM hItem = pTree->InsertItem(&TI);
pTree->SetItemData(hItem, dwData);
// 현재 아이템에 자식 아이템이 있다면
HTREEITEM hChildItem = pTree->GetChildItem(hSrcItem);
if(hChildItem)
{
// 자식 아이템이 있다면 같이 이동하자.
MoveChildTreeItem(pTree, hChildItem, hItem);
}
// 확장 여부를 알아서 똑같이 하자.
TVITEM item;
item.mask = TVIF_HANDLE;
item.hItem = hSrcItem;
pTree->GetItem(&item);
if(item.state & TVIS_EXPANDED)
{
pTree->Expand(hItem, TVE_EXPAND);
}
// 아이템을 선택하자.
pTree->SelectItem(hItem);
// 기존 아이템을 제거한다.
pTree->DeleteItem(hSrcItem);
return TRUE;
}
// 현재 트리의 모든 아이템 데이터 이동
BOOL MoveChildTreeItem(CTreeCtrl *pTree, HTREEITEM hChildItem,
HTREEITEM hDestItem)
{
HTREEITEM hSrcItem = hChildItem;
while(hSrcItem)
{
// 이동할 아이템의 정보를 알아내자.
TVITEM TV;
char str[256];
ZeroMemory(str, sizeof(str));
TV.hItem = hSrcItem;
TV.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TV.pszText = str;
TV.cchTextMax = sizeof(str);
m_ctrTree.GetItem(&TV);
DWORD dwData = pTree->GetItemData(hSrcItem);
// 아이템을 추가 하자.
TVINSERTSTRUCT TI;
TI.hParent = hDestItem;
TI.hInsertAfter = TVI_LAST;
TI.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
TI.item.iImage = TV.iImage;
TI.item.iSelectedImage = TV.iSelectedImage;
TI.item.pszText = TV.pszText;
HTREEITEM hItem = pTree->InsertItem(&TI);
pTree->SetItemData(hItem, dwData);
// 현재 아이템에 자식 아이템이 있다면
HTREEITEM hChildItem = pTree->GetChildItem(hSrcItem);
// pTree->GetNextItem(hSrcItem, TVGN_CHILD);
if(hChildItem)
{
MoveChildTreeItem(pTree, hChildItem, hItem);
}
// 확장 여부를 알아서 똑같이 하자.
TVITEM item;
item.mask = TVIF_HANDLE;
item.hItem = hSrcItem;
pTree->GetItem(&item);
if(item.state & TVIS_EXPANDED)
{
pTree->Expand(hItem, TVE_EXPAND);
}
// 다음 아이템을 알아보자.
hSrcItem = pTree->GetNextItem(hSrcItem, TVGN_NEXT);
}
// 기존 아이템을 제거한다.
pTree->DeleteItem(hChildItem);
return TRUE;
}
댓글 없음:
댓글 쓰기