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);