Delphi. Компоненти і Класи. TListView
Існує досить зручний спосіб прокрутки списків: якщо користувач водить курсором миші по елементах списку з натиснутою лівою кнопкою, то виділяється той елемент, над яким знаходиться курсор. А якщо курсор буде вищою або нижчою списку, то починається прокрутка. Про те, як таке зробити для ListView, ми сьогодні і поговоримо.
По-перше, потрібно зробити виділення елементів, над якими знаходиться курсор миші (при натиснутій лівій кнопці). Для знаходження елемента за координатами курсору зручно використовувати функцію GetItemAt. Щоб змінити виділення, потрібно змінити властивості Selected і ItemFocused.
Щоб відловлювати події миші при виході курсора за кордону ListView потрібно "сказати" WIndows, що миша зараз "моя". Для цього використовується функція SetCapture (щоб сказати, що "миша мені більше не потрібна", використовується функцією ReleaseCapture). Оскільки GetItemAt в разі виходу курсора за кордону ListView повертає порожній елемент (nil), додатково цей випадок можна не перевіряти. Мінлива d приймає позитивне значення, якщо прокрутка буде відбуватися вниз і негативне в іншому випадку. Модуль d вказує на те, скільки елементів за раз буде прокручуватися. Потрібно це для зміни швидкості прокрутки (тут швидкість прокрутки залежить від того, наскільки далеко знаходиться курсор від ListView).
Сама прокрутка здійснюється в процедурі Move. До номеру виділеного елемента додається d. Якщо новий номер виходить за рамки допустимого значення, він встановлюється в 0 або Items.Count - 1. Далі відбувається перевірка: якщо номер виділеного елемента збігається в новим номером, то робити нічого не потрібно. В іншому випадку потрібно змінити значення Selected і ItemFocused, а також прокрутити список. Для останнього зручно використовувати процедуру MakeVisible. Вона прокручує список так, щоб вказаний елемент виявився видатним.
Щоб список міг прокручуватися при нерухомій миші, потрібно зробити Timer, який би періодично викликав Move. Якщо курсор знову виявляється над ListView або користувач відпускає ліву кнопку миші, Timer вимикається.
var
d: integer = 0;
procedure Move;
var
NewIndex: integer;
begin
with Form1.ListView1 do if Assigned (Selected) then begin
NewIndex: = Selected.Index + d;
if NewIndex <0
then NewIndex: = 0
else if NewIndex> = Items.Count
then NewIndex: = Items.Count - 1;
if NewIndex <> Selected.Index then begin
Selected: = Items [NewIndex];
ItemFocused: = Selected;
Selected.MakeVisible (true);
end;
end;
end;
procedure TForm1.FormCreate (Sender: TObject);
var
i: integer;
li: TListitem;
lc: TListColumn;
begin
Timer1.Interval: = 100;
ListView1.ViewStyle: = vsReport;
lc: = ListView1.Columns.Add;
lc.Caption: = 'Caption';
lc.AutoSize: = true;
lc: = ListView1.Columns.Add;
lc.Caption: = 'SubItem';
lc.AutoSize: = true;
ListView1.Items.BeginUpdate;
for i: = 1 to 1000 do begin
li: = ListView1.Items.Add;
li.Caption: = 'Item' + IntToStr (i);
li.SubItems.Add ( 'SubItem' + IntToStr (i));
end;
ListView1.Items.EndUpdate;
end;
procedure TForm1.ListView1MouseDown (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
SetCapture (ListView1.Handle);
end;
procedure TForm1.ListView1MouseMove (Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
li: TListItem;
begin
if ssLeft in Shift then with ListView1 do begin
li: = GetItemAt (10, Y);
if Assigned (li) then begin
Timer1.Enabled: = false;
Selected: = li;
ItemFocused: = ListView1.Selected;
end else begin
if Y> = ListView1.ClientHeight
then d: = (Y - ListView1.ClientHeight) div 20 + 1
else d: = Y div 20 - 1;
if Timer1.Enabled = false then begin
Move;
Timer1.Enabled: = true;
end;
end;
end;
end;
procedure TForm1.ListView1MouseUp (Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Timer1.Enabled: = false;
ReleaseCapture;
end;
procedure TForm1.Timer1Timer (Sender: TObject);
begin
Move;
end;