Как перетащить элемент Tree-View
В этом разделе демонстрируется код для обработки перетаскивания и удаления элементов представления дерева. Пример кода состоит из трех функций. Первая функция начинает операцию перетаскивания, вторая функция перетаскивает изображение, а третья функция заканчивает операцию перетаскивания.
Заметка
Перетаскивание элемента представления дерева обычно включает обработку кода уведомления 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. Перетаскивание элемента представления дерева
Перетащите элемент представления дерева, вызвав функцию ImageList_DragMove, когда родительское окно получает сообщение WM_MOUSEMOVE, как показано в следующем примере. В примере также показано, как выполнять определение попаданий во время операции перетаскивания, чтобы определить, следует ли выделять другие элементы в древовидной структуре в качестве целевых объектов.
// 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. Завершение операции перетаскивания представления дерева
В следующем примере показано, как завершить операцию перетаскивания. Функция ImageList_EndDrag вызывается, когда родительское окно получает сообщение WM_LBUTTONUP. Дескриптор элемента управления "Представление дерева" передается функции.
// 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;
}
Связанные разделы