SS}}

Delphi.int.ru — Портал программистов

Вход Регистрация | Забыли пароль?

События

Сегодня:
Вопросы0    Ответы0    Мини-форумы0


Последние:
Вопрос02.04, 13:45 / #6688
Ответ29.03, 23:32 / #6682
Новости30 апреля 2012


Сейчас онлайн:
На сайте — 22
На IRC-канале — 1

Ссылки
Аудиореклама в торговых центрах с помощью ПО от компании Market Music

Поменять местами элементы в 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 »

Рейтинг статьи: нет Голосов: нет Ваша оценка:

Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.


Статьи, похожие по тематике

 

Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:

Ссылка для форумов (BBCode):

Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:56}} (буква a — латинская) — только адрес статьи (URL);
{{статья:56}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).

Поделитесь ссылкой в социальных сетях:


Комментарии читателей к данной статье

Пока нет комментариев к данной статье. Оставьте свой и он будет первым.

Оставлять комментарии к статьям могут только зарегистрированные пользователи.