Stopp, bevor du jetzt sofort anfängst zu sagen: "Das ist doch sowieso schon drin!".
Das stimmt, aber es gibt Fälle, in denen man Einfluss auf das gesamte Scroll-Verhalten haben muss, den man bei den Gesture Events nicht hat.
Ich probierte lange herum mit den Gesture Events, bis ich mir ein Herz fasste und alles selber schrieb.
Hier zeige ich euch, wie man ein natürliches Scroll-Verhalten mittels Mouse Events implementiert.
Also eigentlich ist es gar kein richtiges Tutorial. Ich wollte einfach mal den Code ins Netz bringen; vielleicht hilft er ja jemandem...
Ich behaupte nicht, dass mein Code besonders schön(!
) oder effizient ist, also, wenn ihr Verbesserungsvorschläge habt, schreibt sie!
Code:
FMouseDown : Boolean;
FStartMousePoint : TPoint;
FThisMousePoint : TPoint;
FLastMousePoint : TPoint;
FStartTime : Cardinal;
procedure TForm1.ListView1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if FMouseDown then
begin
FLastMousePoint := FThisMousePoint;
FThisMousePoint := TPoint.Create(X,Y);
if (Y - FLastMousePoint.Y > 0) then
begin
//Wenn die Richtung zum ersten Mal positiv ist
if (Vorzeichen <> Plus) then
begin
FStartMousePoint := FThisMousePoint;
//Zeit stoppen
FStartTime := GetTickCount();
end;
Vorzeichen := Plus;
end
else if (Y - FLastMousePoint.Y < 0) then
begin
//Wenn die Richtung zum ersten Mal negativ ist
if (Vorzeichen <> Minus) then
begin
FStartMousePoint := FThisMousePoint;
//Zeit stoppen
FStartTime := GetTickCount();
end;
Vorzeichen := Minus;
end;
//Deselect item
if Assigned(ListView1.Selected) then
ListView1.Selected.MakeVisible(false);
//Scroll
ListView1.Scroll(0, FLastMousePoint.Y - FThisMousePoint.Y);
end;
end;
procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FMouseDown := true;
FStartMousePoint := TPoint.Create(X,Y);
FThisMousePoint := FStartMousePoint;
FLastMousePoint := FThisMousePoint;
//Zeit stoppen
FStartTime := GetTickCount();
//Deselect item
if Assigned(ListView1.Selected) then
ListView1.Selected.MakeVisible(false);
end;
//Wenn ich nur von der ListView den MouseEvent nähme, würde ein Absetzen des Fingers auch nur auf der ListView registriert...
//Wer nicht weiss woher ich den Event habe: AppEvents ist ne Komponente und das ist der OnMessage Event
procedure TForm1.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
var
i : Integer;
dTime : Double;
dPos : Integer;
speed : Integer;
procedure Delay(Milliseconds: Integer);
{by Hagen Reddmann}
var
Tick: DWORD;
Event: THandle;
begin
Event := CreateEvent(nil, False, False, nil);
try
Tick := GetTickCount + DWORD(Milliseconds);
while (Milliseconds > 0) and
(MsgWaitForMultipleObjects(1, Event, False, Milliseconds,
QS_ALLINPUT) <> WAIT_TIMEOUT) do
begin
Application.ProcessMessages;
Milliseconds := Tick - GetTickCount;
end;
finally
CloseHandle(Event);
end;
end;
begin
if (Msg.message = WM_LBUTTONUP) and (FMouseDown) then
begin
FMouseDown := false;
//Get speed
dTime := (GetTickCount() - FStartTime) / 100;//Resultatgrösse optimieren
dPos := (FStartMousePoint.Y - FThisMousePoint.Y);
if (dTime <> 0) then
speed := Round(dPos / dTime)
else
exit;
//Deselect item
if Assigned(ListView1.Selected)then
ListView1.Selected.MakeVisible(false);
//Decelerate
if (Vorzeichen = Minus) then
for i := speed downto 0 do //+
begin
if FMouseDown = false then
Delay(5)
else
exit;
ListView1.Scroll(0, i DIV 15);
end
else
for i := speed to 0 do //-
begin
if FMouseDown = false then
Delay(5)
else
exit;
ListView1.Scroll(0, i DIV 15);
end;
end;
end;