Compartilhar via


Como arrastar um item de exibição de árvore

Este tópico demonstra o código para lidar com arrastar e soltar itens de exibição em árvore. O código de exemplo consiste em três funções. A primeira função inicia a operação de arrastar, a segunda função arrasta a imagem e a terceira função termina a operação de arrastar.

Observação

Arrastar um item de exibição em árvore geralmente envolve o processamento do código de notificação TVN_BEGINDRAG (ou TVN_BEGINRDRAG), a mensagem WM_MOUSEMOVE e a mensagem WM_LBUTTONUP (ou WM_RBUTTONUP). Também envolve o uso das funções Listas de imagens para desenhar o item à medida que ele está sendo arrastado.

 

O que você precisa saber

Tecnologias

Pré-requisitos

  • C/C++
  • Programação da interface do usuário do Windows

Instruções

Etapa 1: Iniciando a operação de arrastar de exibição em árvore

Um controle de exibição em árvore envia à janela pai um código de notificação TVN_BEGINDRAG (ou TVN_BEGINRDRAG) sempre que o usuário começa a arrastar um item. A janela pai recebe a notificação na forma de uma mensagem de WM_NOTIFY cujo parâmetro lParam é o endereço de uma estrutura NMTREEVIEW. Os membros dessa estrutura incluem as coordenadas de tela do ponteiro do mouse e uma estrutura TVITEM que contém informações sobre o item a ser arrastado.

O exemplo a seguir mostra como processar a mensagem WM_NOTIFY para obter 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; 

Iniciar a operação de arrastar envolve o uso da função ImageList_BeginDrag. Os parâmetros da função incluem o identificador para a lista de imagens que contém a imagem a ser usada durante a operação de arrastar e o índice da imagem. Você pode fornecer sua própria lista de imagens e imagem, ou pode fazer com que o controle de exibição em árvore as crie para você usando a mensagem TVM_CREATEDRAGIMAGE.

Como a imagem de arrastar substitui o ponteiro do mouse durante a operação de arrastar, ImageList_BeginDrag requer que você especifique um ponto de acesso dentro da imagem. As coordenadas do ponto de acesso são relativas ao canto superior esquerdo da imagem. ImageList_BeginDrag também requer que você especifique o local inicial da imagem de arraste. Um aplicativo normalmente define o local inicial para que o ponto de acesso da imagem de arrastar corresponda ao do ponteiro do mouse no momento em que o usuário iniciou a operação de arrastar.

A função a seguir demonstra como começar a arrastar um item de exibição em árvore. Ele usa a imagem de arraste fornecida pelo controle de exibição em árvore e obtém o retângulo delimitador do item para determinar o ponto apropriado para o ponto de acesso. As dimensões do retângulo delimitador são as mesmas da imagem.

A função captura a entrada do mouse, fazendo com que as mensagens do mouse sejam enviadas para a janela pai. A janela pai precisa das mensagens de WM_MOUSEMOVE subsequentes para determinar onde arrastar a imagem e a mensagem WM_LBUTTONUP para determinar quando encerrar a operação de arrastar.

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

} 

Etapa 2: Arrastando o item de exibição em árvore

Você arrasta um item de exibição em árvore chamando a função ImageList_DragMove quando a janela pai recebe uma mensagem WM_MOUSEMOVE, como mostra o exemplo a seguir. O exemplo também demonstra como executar o teste de ocorrências durante a operação de arrastar para determinar se outros itens devem ser realçados no modo de exibição de árvore como destinos de uma operação de arrastar e soltar.

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

Etapa 3: Encerrando a operação de arrastar de exibição em árvore

O exemplo a seguir mostra como encerrar uma operação de arrastar. A função ImageList_EndDrag é chamada quando a janela pai recebe uma mensagem WM_LBUTTONUP. O identificador do controle tree-view é passado para a função.

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

Usando controles de exibição em árvore

Exemplo de CustDTv ilustra o desenho personalizado em um controle Tree-View