Partager via


Guide pratique pour faire glisser un élément Tree-View

Cette rubrique présente le code permettant de gérer le glisser-déplacer d’éléments d’arborescence. L’exemple de code se compose de trois fonctions. La première fonction commence l’opération de glissement, la deuxième fonction fait glisser l’image et la troisième fonction termine l’opération de glissement.

Notes

Faire glisser un élément d’arborescence implique généralement le traitement du code de notification TVN_BEGINDRAG (ou TVN_BEGINRDRAG), du message WM_MOUSEMOVE et du message WM_LBUTTONUP (ou WM_RBUTTONUP). Elle implique également l’utilisation des fonctions Listes d’images pour dessiner l’élément au fur et à mesure qu’il est déplacé.

 

Bon à savoir

Technologies

Prérequis

  • C/C++
  • Programmation de l’interface utilisateur Windows

Instructions

Étape 1 : Début de l’opération de glissement d’arborescence

Un contrôle arborescence envoie à la fenêtre parente un code de notification TVN_BEGINDRAG (ou TVN_BEGINRDRAG) chaque fois que l’utilisateur commence à faire glisser un élément. La fenêtre parente reçoit la notification sous la forme d’un message WM_NOTIFY dont le paramètre lParam est l’adresse d’une structure NMTREEVIEW . Les membres de cette structure incluent les coordonnées d’écran du pointeur de la souris et une structure TVITEM qui contient des informations sur l’élément à glisser.

L’exemple suivant montre comment traiter le message WM_NOTIFY pour obtenir 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; 

Le début de l’opération de glissement implique l’utilisation de la fonction ImageList_BeginDrag . Les paramètres de la fonction incluent le handle de la liste d’images qui contient l’image à utiliser pendant l’opération de glissement et l’index de l’image. Vous pouvez soit fournir votre propre liste d’images et votre propre image, soit demander au contrôle arborescence de les créer pour vous à l’aide du message TVM_CREATEDRAGIMAGE .

Étant donné que l’image de glissement remplace le pointeur de la souris pendant la durée de l’opération de glissement, ImageList_BeginDrag vous oblige à spécifier un point chaud dans l’image. Les coordonnées du point chaud sont relatives au coin supérieur gauche de l’image. ImageList_BeginDrag vous oblige également à spécifier l’emplacement initial de l’image de glissement. Une application définit généralement l’emplacement initial afin que le point chaud de l’image de glissement corresponde à celui du pointeur de la souris au moment où l’utilisateur a commencé l’opération de glissement.

La fonction suivante montre comment commencer à faire glisser un élément d’arborescence. Il utilise l’image de glissement fournie par le contrôle d’arborescence et obtient le rectangle englobant de l’élément pour déterminer le point approprié pour le point chaud. Les dimensions du rectangle englobant sont les mêmes que celles de l’image.

La fonction capture l’entrée de la souris, provoquant l’envoi de messages de souris à la fenêtre parente. La fenêtre parente a besoin des messages WM_MOUSEMOVE suivants pour déterminer où faire glisser l’image et le message WM_LBUTTONUP pour déterminer quand mettre fin à l’opération de glissement.

// 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; 

} 

Étape 2 : Faire glisser l’élément d’arborescence

Vous faites glisser un élément d’arborescence en appelant la fonction ImageList_DragMove lorsque la fenêtre parente reçoit un message WM_MOUSEMOVE , comme le montre l’exemple suivant. L’exemple montre également comment effectuer des tests de positionnement pendant l’opération de glissement pour déterminer s’il faut mettre en surbrillance d’autres éléments dans l’arborescence en tant que cibles d’une opération de glisser-déplacer.

// 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; 
}

Étape 3 : Mettre fin à l’opération de glissement d’arborescence

L’exemple suivant montre comment mettre fin à une opération de glissement. La fonction ImageList_EndDrag est appelée lorsque la fenêtre parente reçoit un message WM_LBUTTONUP . Le handle du contrôle tree-view est passé à la fonction .

// 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; 
} 

Utilisation de contrôles Tree-View

L’exemple CustDTv illustre un dessin personnalisé dans un contrôle Tree-View