Mam ListBoxa na formie. Rozumiem, że parentem listBoxa jest właśnie ta forma.
Załóżmy, że listBox ma 100 itemów i height 200. Aby zobaczyć dalsze, trzeba go scrollować.
Teraz chcę zrobić tak, że podczas drag&drop, gdy użytkownik wyjedzie kursorem myszy poza listBox(kursor będzie na formie), wtedy listBox się zescrolluje, a item, który jest scrollowany zmieni swoją pozycję.
Na obszarze samego ListBoxa drag&drop działa mi ok, ale schody zaczynają się jak wyjadę kursorem za listBoxa(na formę)
Do onDragOver formy wpisałem coś takiego(lb to oczywiście mój ListBox):
begin
if y>(lb.Top+lb.Height-5) then lb.Perform(WM_VScroll, 1, 0);
if (toDrag+1)>(lb.Count-1) then toDrag:=lb.Count-1
else
begin
lb.Items.Move(toDrag, toDrag+1);
toDrag:=toDrag+1;
end;
end;
na razie zrobiłem tylko połowę(dla itemów, które mają być przesuwane w dół)
Zasada działania tego ma być taka:
Program sprawdza, czy kursor myszy wyjechał poza ListBox w dół, jeśli tak, to ListBox ma się scrollować jedną linię w dół
Następnie sprawdza, czy wartość o jeden większa od indeksu przesuwanego itema jest większa od ilości itemów. Jeśli tak to znaczy, że przesuwany item jest już na ostatniej pozycji i nie trzeba go dalej przesuwać. Natomiast jeśli nie, to wtedy przesuwa item o indeksie toDrag na pozycję o jeden większą. Czyli np. item o indeksie 34 przesuwa na pozycję 35 (no i automatycznie 35 na 34 oczywiście)
Następnie zmienia indeks przesuwanego itema o plus jeden, chyba wiadomo dlaczego.
Problem polega na tym, że listBox nie chce się scrollować. Tzn. robi to tak jakby chciał, a nie mógł. Niby pasek przewijania lekko się przesuwa, ale od razu wraca na poprzednią pozycję. Tak jakby skacze. Natomiast item przesuwa się w porządku.
Co ciekawe scrollBar przesuwa się tak na poważnie dopiero wtedy, gdy item przesuwany znajduje się na ostatniej pozycji.
Poniżej zamieszczam jeszcze kilka szczegółów, bo może będą potrzebne:
początkowa wartość toDrag to w onClick listBoxa: toDrag:=lb.itemindex;
MoseMove listBoxa:
if ssLeft in Shift then lb.BeginDrag(true);
dragOver listBoxa:
var
pos: TPoint;
begin
pos.X:=5;
pos.Y:=y;
//sprawdzamy, czy użytkownik wyjechał poza listBoxa
if (y<=0) or (y>=(lb.Height)-5) then
begin
//użytkownik wyjechał
if y<=0 then
begin
lb.Perform(WM_VSCROLL, 0, 0);
pos.Y:=0;
end else
begin
lb.Perform(WM_VSCROLL, 1, 0);
pos.Y:=(lb.Height-5);
end;
end;
{powyższe sprawdzenie działa, gdy użytkownik dojdzie myszą na wertykalne krańce listBoxa}
lb.Items.Move(toDrag, lb.ItemAtPos(pos, true));
toDrag:=lb.ItemAtPos(pos, true);