Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

ListView - не перескакивать обратно на выделенный элемент

70K
28 апреля 2011 года
bro
4 / / 24.04.2011
Здравствуйте. Помогите, пожалуйста, с проблемой:

Использую ListView в виртуальном режиме, vsReport. Итемов около 700, есть вертикальный скролл. Если выделить какую-либо строчку, а потом прокрутить ListView так, чтобы выделенную строчку не было видно, то скролл самопроизвольно возвращается обратно при изменении количества итемов. Как этого избежать?

Иными словами: Мне нужно избежать автоматического "MakeVisible" для выделенного элемента. То есть, скролл должен в любой ситуации остаться на своём месте. (именно там, куда прокрутил его юзер, а не в конце списка и не на выделенном итеме)

P.S. уже оставлял сообщение на другом форуме, но его, видимо, DDoSят :(
19K
29 апреля 2011 года
Alegun
269 / / 10.09.2010
Перепробовал много вариантов "чтоб испортить" скроллинг в ListView, но всё работает правильно, так и не удалось создать подобные приведенным условия:). Могу ошибаться, но возможно после добавления итемок происходит переход в режим редактора (EditCaption), если это так, то тогда само-собой будет переход к выделёнке, в остальных случаях такого не происходит. Нужно пользовать метод CancelEdit.

З.Ы. На кофейной гуще трудно гадать, поэтому желательно приводить примерчик кода, что и как там происходит, тогда и DDoSить никто не будет:D
70K
29 апреля 2011 года
bro
4 / / 24.04.2011
Alegun, вот проектик, код минимальный: [ATTACH]5103[/ATTACH]
Для воспроизведения проблемы попробуйте, к примеру, выделить число "2", а потом попытаться удержать скролл на середине списка. P.S.: ReadOnly также не спасает, попробовал.
19K
29 апреля 2011 года
Alegun
269 / / 10.09.2010
Цитата: bro
...Для воспроизведения проблемы попробуйте, к примеру, выделить число "2", а потом попытаться удержать скролл на середине списка...



Ук bro, замените в тике таймера конструкцию

ListView1.Items.Count:= ListView1.Items.Count + 1;

на

ListView1.Items.Add;

Так всё работает.

70K
29 апреля 2011 года
bro
4 / / 24.04.2011
Alegun, большое спасибо за совет! В первый раз после каждой смены выделения таки перескакивает, но уже гораздо лучше. (а нет ли компонентов, в которых сей недостаток устранён?)
70K
08 января 2012 года
bro
4 / / 24.04.2011
Ап той самой темке...

Вот печаль, обнаружилось, что ListView1.Items.Add вызывает утечку памяти.
Items.Insert(0) тоже вызывает утечку.

ListView1.Items.Count:= ... в свою очередь не вызывает никакой утечки.

Какие будут предложения? =)

//----------

Всю ночь мучался, в итоге родилось вот это (изменение оригинального сырца):

Цитата:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ExtCtrls, CommCtrl;

type
TForm1 = class(TForm)
ListView1: TListView;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
procedure ListView1Data(Sender: TObject; Item: TListItem);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := IntToStr(Item.Index);
Item.SubItems.Add(IntToStr(Sqr(Item.Index)));
end;

function LVGetTopItem(LV: TListView): Integer;
begin
Result := SendMessage(LV.Handle, LVM_GETTOPINDEX, 0, 0);
end;

procedure LVSetTopItem(pListV: TListView; ItemID: Integer);
var
x1, x2: Integer;
begin
x1 := ItemID;
x2 := x1 + pListV.VisibleRowCount - 1;
// we can't move upper then 0
if (x1 < 0) then
Exit;
// check bounds
if (x2 > pListV.Items.Count - 1) then
Exit;
// check if we are already at position we need
if (x1 = LVGetTopItem(pListV)) then
Exit;

// LockPListWindowUpdate;
pListV.Items.Item[x1].MakeVisible(False);
pListV.Items.Item[x2].MakeVisible(False);
// UnLockPListWindowUpdate;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
itemOldIndex: Integer;
begin
itemOldIndex := 0;
itemOldIndex := LVGetTopItem(ListView1);
//
Timer1.Enabled := False;
ListView1.Items.Count := ListView1.Items.Count + 1;
Timer1.Enabled := True;
//
Form1.Caption := (IntToStr(itemOldIndex));
//
LVSetTopItem(ListView1, itemOldIndex);
end;

end.



По-другому ну никак не выходило - пробовал ListView_EnsureVisible(ListView1.Handle, itemOldIndex, False); и много чего ещё.

Единственная проблема в том, что весь этот код не пашет внутри OnData. Почему - хз.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог