Cómo arrastrar un elemento de Tree-View
En este tema se muestra el código para controlar el arrastre y la colocación de elementos de vista de árbol. El código de ejemplo consta de tres funciones. La primera función inicia la operación de arrastre, la segunda función arrastra la imagen y la tercera función finaliza la operación de arrastre.
Nota
Arrastrar un elemento de vista de árbol normalmente implica procesar el código de notificación de TVN_BEGINDRAG (o TVN_BEGINRDRAG), el mensaje de WM_MOUSEMOVE y el mensaje de WM_LBUTTONUP (o WM_RBUTTONUP). También implica el uso de las funciones Listas de imágenes para dibujar el elemento a medida que se arrastra.
Lo que necesita saber
Tecnologías
Requisitos previos
- C/C++
- Programación de la interfaz de usuario de Windows
Instrucciones
Paso 1: Iniciar la operación de arrastrar vista de árbol
Un control de vista de árbol envía a la ventana primaria un código de notificación de TVN_BEGINDRAG (o TVN_BEGINRDRAG) cada vez que el usuario empieza a arrastrar un elemento. La ventana primaria recibe la notificación en forma de un mensaje de WM_NOTIFY cuyo parámetro lParam es la dirección de una estructura NMTREEVIEW . Los miembros de esta estructura incluyen las coordenadas de pantalla del puntero del mouse y una estructura TVITEM que contiene información sobre el elemento que se va a arrastrar.
En el ejemplo siguiente se muestra cómo procesar el mensaje de WM_NOTIFY para obtener 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;
El inicio de la operación de arrastre implica el uso de la función ImageList_BeginDrag . Los parámetros de la función incluyen el identificador de la lista de imágenes que contiene la imagen que se va a usar durante la operación de arrastre y el índice de la imagen. Puede proporcionar su propia lista de imágenes e imagen, o bien puede hacer que el control de vista de árbol los cree automáticamente mediante el mensaje TVM_CREATEDRAGIMAGE .
Dado que la imagen de arrastre reemplaza el puntero del mouse durante la operación de arrastre, ImageList_BeginDrag requiere que especifique una zona activa dentro de la imagen. Las coordenadas de la zona activa son relativas a la esquina superior izquierda de la imagen. ImageList_BeginDrag también requiere que especifique la ubicación inicial de la imagen de arrastre. Normalmente, una aplicación establece la ubicación inicial para que la zona activa de la imagen de arrastre corresponda a la del puntero del mouse en el momento en que el usuario inició la operación de arrastre.
La siguiente función muestra cómo empezar a arrastrar un elemento de vista de árbol. Usa la imagen de arrastre proporcionada por el control de vista de árbol y obtiene el rectángulo delimitador del elemento para determinar el punto adecuado para el punto activo. Las dimensiones del rectángulo delimitador son las mismas que las de la imagen.
La función captura la entrada del mouse, lo que hace que los mensajes del mouse se envíen a la ventana primaria. La ventana primaria necesita los siguientes mensajes de WM_MOUSEMOVE para determinar dónde arrastrar la imagen y el mensaje de WM_LBUTTONUP para determinar cuándo finalizar la operación de arrastre.
// 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;
}
Paso 2: Arrastrar el elemento de vista de árbol
Para arrastrar un elemento de vista de árbol, llame a la función ImageList_DragMove cuando la ventana primaria reciba un mensaje de WM_MOUSEMOVE , como se muestra en el ejemplo siguiente. En el ejemplo también se muestra cómo realizar pruebas de posicionamiento durante la operación de arrastre para determinar si se resaltan otros elementos de la vista de árbol como destinos de una operación de arrastrar y colocar.
// 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;
}
Paso 3: Finalizar la operación de arrastrar vista de árbol
En el ejemplo siguiente se muestra cómo finalizar una operación de arrastre. Se llama a la función ImageList_EndDrag cuando la ventana primaria recibe un mensaje WM_LBUTTONUP . El identificador del control de vista de árbol se pasa a la función .
// 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;
}
Temas relacionados