Поменять местами элементы в ListView. Миссия выполнима
Уж сколько имею опыта программировании на Delphi, а с такой задачей пришлось столкнуться впервые. Метода Exchange или Swap, к своему удивлению, не нашёл.
Что мы там ещё имеем? Свойство Index у элемента только на чтение, да и, само собой, информацию об одном из элементов нужно слить в какой-то временный буфер. Возникло горячее желание создать отдельно стоящий TListItem без владельца и сделать классический треугольник как в каком-нибудь учебнике. Осторожно заглянув в исходный код, возможна ли такая картина, ужаснулся от кода деструктора:
destructor TListItem.Destroy; begin FDeleting := True; if Owner.Owner.FLastDropTarget = Self then Owner.Owner.FLastDropTarget := nil; if ListView.HandleAllocated then ListView_DeleteItem(Handle, Index); FSubItems.Free; inherited Destroy; end;
Дело пахло AccessViolation'ом. Собирался было воспользоваться комбоприемом Insert-копирование-Delete, но быстро взял себя в руки, так как изобретателей велосипедов у нас в стране хватает. Вспомнил, где такая задача была у одного из моих коллег, и полез в его код.
//-------------------------------------------------------------- // Обмен между двумя Item //-------------------------------------------------------------- procedure TSyncForm.SwapItems(Index1, Index2: Integer); Var NewIndex: Integer; begin With SyncListView do begin Items.BeginUpdate; Items.Add(); NewIndex := Items.Count-1; try Items[NewIndex] := Items[Index1]; Items[Index1] := Items[Index2]; Items[Index2] := Items[NewIndex]; Items.Delete(NewIndex); finally Items.EndUpdate; end; end; end;
Хотел уже было перетаскивать этот код в свой проект, но как-то напрягало меня это движение «туда-сюда» — «Add-Delete>». Обратившись к поисковикам, обнаружил, что в интернете данный код является стандартом де`факто в деле обмена элементами, и был практически скопирован с одной из страниц.
Покопавшись ещё немного в исходниках VCL, решил попробовать воспользоваться низкоуровневыми функциями модуля CommCtrl. В результате у меня появилась такая процедура:
uses CommCtrl; ..... procedure SwapItem(aList: TListView; aIndex1, aIndex2: Integer); var item1, item2: TLVItem; begin item1.mask := LVIF_PARAM; item1.iSubItem := 0; item2 := item1; item1.iItem := aIndex1; item2.iItem := aIndex2; if not ListView_GetItem(aList.Handle, item1) or not ListView_GetItem(aList.Handle, item2) then Exit; item1.iItem := aIndex2; item2.iItem := aIndex1; if not ListView_SetItem(aList.Handle, item1) or not ListView_SetItem(aList.Handle, item2) then raise EListError.CreateFmt('Error exchange items %d and %d!', [aIndex1, aIndex2]); end;
Квазимодо, конечно, внешностью не блещет, но работу делает. Жду отзывов.
Автор: DNK
Статья добавлена: 25 июня 2013
Следующая статья: Обучающий курс. 1. Введение в Delphi »
Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.
Статьи, похожие по тематике
- Web-страничка внутри приложения
- Бегущая строка
- Введение в Synapse
- Виртуальный ListView
- Выравнивание компонентов
- Диалог в стиле wizard'а
- Добавляем компонент в стандартный Message Dialog
- Использование компонента TCoolBar
- Компоненты Ribbon в Delphi
- Написание инсталлятора на Delphi
- Обучающий курс. 13. Ввод и вывод
- Обучающий курс. 6. Обзор свойств формы
- Обучающий курс. 7. Обзор палитры компонент - Standard, Additional
- Перемещение TImage по форме во время работы приложения
- Рисуем график функции в Delphi
- Создание интерфейса с использованием PNG-графики
- Создание своего диалога выбора цвета
- Читаем цитаты с bash.org.ru своей программой
Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:
Ссылка для форумов (BBCode):
Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:56}} (буква a — латинская) — только адрес статьи (URL);
{{статья:56}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).
Поделитесь ссылкой в социальных сетях:
Комментарии читателей к данной статье
Пока нет комментариев к данной статье. Оставьте свой и он будет первым.
Оставлять комментарии к статьям могут только зарегистрированные пользователи.