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;
}
Tópicos relacionados