如何拖曳樹視圖專案

本主題示範用來處理樹檢視專案的拖放程序代碼。 範例程式代碼包含三個函式。 第一個函式會開始拖曳作業、第二個函式拖曳影像,而第三個函式結束拖曳作業。

注意

拖曳樹視圖專案通常涉及處理 TVN_BEGINDRAG (或 TVN_BEGINRDRAG)通知程式代碼、 WM_MOUSEMOVE 訊息,以及 WM_LBUTTONUP (或 WM_RBUTTONUP) 訊息。 它也牽涉到使用 影像清單 函式在拖曳專案時繪製專案。

 

您需要知道的事項

技術

必要條件

  • C/C++
  • Windows 使用者介面程序設計

指示

步驟 1:開始樹視圖拖曳作業

每當用戶開始拖曳專案時,樹視圖控件會將TVN_BEGINDRAG(或TVN_BEGINRDRAG)通知碼傳送給父視窗。 父視窗會以WM_NOTIFY訊息的形式接收通知,其 lParam 參數是 NMTREEVIEW 結構的位址。 這個結構的成員包括滑鼠指標的螢幕座標,以及 包含要拖曳之專案相關信息的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 範例說明樹視圖控件中的自定義繪製