트리 보기 항목을 끄는 방법

이 항목에서는 트리 보기 항목의 끌어서 놓기 처리를 위한 코드를 보여 줍니다. 샘플은 세 함수로 구성되어 있습니다. 첫 번째 함수는 끌기 작업을 시작하고, 두 번째 함수는 이미지를 끌고, 세 번째 함수는 끌기 작업을 종료합니다.

참고

일반적으로 트리 보기 항목을 끌려면 TVN_BEGINDRAG(또는 TVN_BEGINRDRAG) 알림 코드, WM_MOUSEMOVE 메시지 및 WM_LBUTTONUP(또는 WM_RBUTTONUP) 메시지를 처리하는 작업이 포함됩니다. 또한 Image Lists 함수를 사용하여 항목을 끌 때 그립니다.

 

알아야 하는 작업

기술

필수 구성 요소

  • C/C++
  • Windows 사용자 인터페이스 프로그래밍

지침

1단계: 트리 보기 끌기 작업 시작

트리 보기 컨트롤은 사용자가 항목을 끌기 시작할 때마다 부모 창에 TVN_BEGINDRAG(또는 TVN_BEGINRDRAG) 알림 코드를 보냅니다. 부모 창은 lParam 매개 변수가 NMTREEVIEW 구조체의 주소인 WM_NOTIFY 메시지 형식으로 알림을 받습니다. 이 구조체의 멤버에는 마우스 포인터의 화면 좌표와 끌 항목에 대한 정보가 포함된 TVITEM 구조체가 포함됩니다.

다음 예제에서는 WM_NOTIFY 메시지를 처리하여 TVN_BEGINDRAG를 가져오는 방법을 보여 줍니다.

    case WM_NOTIFY: 
        switch (((LPNMHDR)lParam)->code) 
        {
            case TVN_BEGINDRAG:
                Main_OnBeginDrag(((LPNMHDR)lParam)->hwndFrom, (LPNMTREEVIEW)lParam);
                break;
        
            // Handle other cases here. 
        }
        break; 

끌기 작업을 시작하려면 ImageList_BeginDrag 함수를 사용해야 합니다. 함수의 매개 변수에는 끌기 작업 중에 사용할 이미지가 포함된 이미지 목록의 핸들과 이미지의 인덱스가 포함됩니다. 사용자 고유의 이미지 목록과 이미지를 제공하거나 트리 보기 컨트롤에서 TVM_CREATEDRAGIMAGE 메시지를 사용하여 만들 수 있습니다.

끌기 이미지는 끌기 작업 기간 동안 마우스 포인터를 대체하므로 ImageList_BeginDrag는 이미지 내에서 핫 스폿을 지정해야 합니다. 핫 스폿의 좌표는 이미지의 왼쪽 위 모서리를 기준으로 합니다. ImageList_BeginDrag는 끌기 이미지의 초기 위치를 지정해야 합니다. 애플리케이션은 일반적으로 사용자가 끌기 작업을 시작했을 때 끌기 이미지의 핫스폿이 마우스 포인터의 핫스폿에 해당하도록 초기 위치를 설정합니다.

다음 함수는 트리 보기 항목 끌기를 시작하는 방법을 보여 줍니다. 트리 보기 컨트롤에서 제공하는 끌기 이미지를 사용하고 항목의 경계 사각형을 가져와 핫 스폿에 적합한 지점을 결정합니다. 경계 사각형의 크기는 이미지의 크기와 동일합니다.

함수는 마우스 입력을 캡처하여 마우스 메시지를 부모 창으로 보냅니다. 부모 창에는 이미지를 끌 위치를 결정하는 후속 WM_MOUSEMOVE 메시지와 끌기 작업을 종료할 시기를 결정하는 WM_LBUTTONUP 메시지가 필요합니다.

// Begin dragging an item in a tree-view control. 
// hwndTV - handle to the image list. 
// lpnmtv - address of information about the item being dragged.
//
// g_fDragging -- global BOOL that specifies whether dragging is underway.

void Main_OnBeginDrag(HWND hwndTV, LPNMTREEVIEW lpnmtv)
{ 
    HIMAGELIST himl;    // handle to image list 
    RECT rcItem;        // bounding rectangle of item 

    // Tell the tree-view control to create an image to use 
    // for dragging. 
    himl = TreeView_CreateDragImage(hwndTV, lpnmtv->itemNew.hItem); 

    // Get the bounding rectangle of the item being dragged. 
    TreeView_GetItemRect(hwndTV, lpnmtv->itemNew.hItem, &rcItem, TRUE); 

    // Start the drag operation. 
    ImageList_BeginDrag(himl, 0, 0, 0);
    ImageList_DragEnter(hwndTV, lpnmtv->ptDrag.x, lpnmtv->ptDrag.x); 

    // Hide the mouse pointer, and direct mouse input to the 
    // parent window. 
    ShowCursor(FALSE); 
    SetCapture(GetParent(hwndTV)); 
    g_fDragging = TRUE; 

    return; 

} 

2단계: 트리 보기 항목 끌기

다음 예제와 같이 부모 창에서 WM_MOUSEMOVE 메시지를 수신할 때 ImageList_DragMove 함수를 호출하여 트리 보기 항목을 끌어옵니다. 또한 이 예제에서는 끌어서 놓기 작업 중에 적중 테스트를 수행하여 트리 보기의 다른 항목을 끌어서 놓기 작업의 대상으로 강조 표시할지 여부를 결정하는 방법을 보여 줍니다.

// Drag an item in a tree-view control, 
// highlighting the item that is the target. 
// hwndParent - handle to the parent window. 
// hwndTV - handle to the tree-view control.
// xCur and yCur - coordinates of the mouse pointer,
//     relative to the parent window. 
//
// g_fDragging - global BOOL that specifies whether dragging is underway.

void Main_OnMouseMove(HWND hwndParent, HWND hwndTV, LONG xCur, LONG yCur) 
{ 
    HTREEITEM htiTarget;  // Handle to target item. 
    TVHITTESTINFO tvht;   // Hit test information. 

    if (g_fDragging) 
    { 
       // Drag the item to the current position of the mouse pointer. 
       // First convert the dialog coordinates to control coordinates. 
       POINT point;
       point.x = xCur;
       point.y = yCur;
       ClientToScreen(hwndParent, &point);
       ScreenToClient(hwndTV, &point);
       ImageList_DragMove(point.x, point.y);
       // Turn off the dragged image so the background can be refreshed.
       ImageList_DragShowNolock(FALSE); 
                
        // Find out if the pointer is on the item. If it is, 
        // highlight the item as a drop target. 
        tvht.pt.x = point.x; 
        tvht.pt.y = point.y; 
        if ((htiTarget = TreeView_HitTest(hwndTV, &tvht)) != NULL) 
        { 
            TreeView_SelectDropTarget(hwndTV, htiTarget); 
        } 
        ImageList_DragShowNolock(TRUE);
    } 
    return; 
}

3단계: 트리 보기 끌기 작업 종료

다음 예제에서는 끌기 작업을 종료는 방법을 보여 줍니다. 부모 창에서 WM_LBUTTONUP 메시지를 수신하면 ImageList_EndDrag 함수가 호출됩니다. 트리 보기 컨트롤의 핸들이 함수에 전달됩니다.

// Stops dragging a tree-view item, releases the 
// mouse capture, and shows the mouse pointer.
//
// g_fDragging - global BOOL that specifies whether dragging is underway.

void Main_OnLButtonUp(HWND hwndTV) 
{ 
    if (g_fDragging) 
    { 
        // Get destination item.
        HTREEITEM htiDest = TreeView_GetDropHilight(hwndTV);
        if (htiDest != NULL)
        {
            // To do: handle the actual moving of the dragged node.
        }
        ImageList_EndDrag(); 
        TreeView_SelectDropTarget(hwndTV, NULL);
        ReleaseCapture(); 
        ShowCursor(TRUE); 
        g_fDragging = FALSE; 
    } 
    return; 
} 

트리 뷰 컨트롤 사용

CustDTv 샘플은 트리 뷰 컨트롤의 사용자 지정 그리기를 보여 줍니다.