[DELPHI] Gesty myszy

0

Witam ponownie ;)

Mam kolejne nietuzinkowe pytanie - jak zrobić w aplikacji gesty myszy. Jak rozpoznać w jakie strony ruszona została mysz w czasie trzymania np. prawego przycisku myszy. Wciskam PPM i program rozpoznaje gesty (Góra/Dół/Lewo/Prawo) aż do puszczenia PPM.

Chciałem to zrobić na dynamicznej tablicy powiedzmy 50 punktów
ARRAY [1..50] OF TPoint;
i przy ruchach myszką dopisywać kolejne punkty i badać przesunięcia dX i dY (deltaX i deltaY). Tylko po osiągnięciu 50 elementu w tablicy trzeba zastępnować stare elementy a tu trzeba by było przesuwać wartości z tablicy a to procedura czasochlonna i będzie procesor zżerała (tak sądzę). I po rozpoznaniu ruchu w daną stronę (gestu) żeby procka dodawała do już rozpoznanych gestów kolejny gest i usuwała oczywiście powtarzające się typu: G,G,D,D,P,D,L,L
G - góra / D - Dół / L-Lewo / P - prawo
i robiła z tego: G,D,P,D,L

Czy to dobre rozwiązanie czy sądzicie że raczej nie, bo pomysł na gesty zrodził się 5 minut temu a rozwiązanie 4 minuty temu :)

I jeszcze jedno: rozpoznawanie chciałbym aby ograniczało mysz po wciśnięciu PPM do Rect'a np. Image'a ale to już pamiętam jak się robiło (ClipCursor(Rect)) albo coś w podobie.

Podajcie jakąś radę lub pomysła. Serdeczne dzięki dla wszystkich pomocnych i oczywiście duży [browar] dla każdego. Odbiór osobisty ;)

0

Zamiast przesuwać wartości w tablicy, po jej przepełnieniu możesz zastosować wskaźnik ostatnio wpisanej pozycji. Jeśli tablica zostanie przepełniona, kolejna wartość zostanie wpisana w pierwszym indeksie tablicy i tam właśnie będzie wskazywał zastosowany wskaźnik.

0

Watpie, zeby w twoim programie user uzywal gestow skladajacych sie z 50 ruchow :D IMO powinienes zrobic tak, W jakims OnMouseMove czy czyms podobnym sprawdzaj czy delta jest powidzmy wieksza niz 100px, jesli tak to zrob nowy element w tablicy. A przemieszczenie w dol, nie doceniasz dzisiejszego sprzetu ;) ewentualnie mozesz zrobic np liste, wtedy po prostu usuwasz pierwszy element.

0

Przede wszystkim zastosuj kolejkę na listach, tak jak wyżej ktoś wspomniał.
Zapisuj pozycję kursora np. co 10 onMouseMove. Im co więcej będziesz zapisywał, tym mniej dokładny będzie musiał być gest. Wyliczaj kolejno kąty, np do poziomu, z funkcji trygonometrycznych (pamiętaj, że wszystkie te funkcje w delphi operują na radianach = stos. DegToRad), zaokrąglaj kąt do pełnych wartości (0*, 45*, 180* itd...) Jeśli któryś z kolei ruch będzie miał inny kąt niż poprzedni, to znaczy, że zmieniono kierunek poruszania myszą. Albo po prostu gest wykonany niedokładnie.
Całą resztę chyba już będziesz sobie w stanie sam naszkrobać.

Pozdrawiam

Tak się właściwie zastanowiłem, że kolejka na listach nie jest potrzebna. Wystarczy zmienna globalna z poprzednim kątem ruchu i tablica dynamiczna z już wykonanymi ruchami, której długość w OnMouseDown będzie ustawiana na 0, a w co np. dziesiątym OnMouseMove, jeśli zostanie wykonany inny ruch niż poprzedni, powiększana o 1 ( i zapisaywany do niej bedzie ten następny ruch). W OnMouseUp porównujesz zawartość tablicy ze zdefiniowanymi wzorcami i wykonujesz daną proc.

0

50 pozycji, każda niech będzie integerem, wyjdzie 5042 - 400 bajtów to będzie mniej-wiecej 100 cykli procesora. myślę, że to nie zajmie więcej niż 1us ;]

0

Dziękuję wszystkim za pomoc. Na bazie Waszej pomocy napisałem takową procedurę:

(Rozpoznawanie odbywa się na TPanel'u)

1. Na formatkę/formę dajemy dwa komponenty: TPanel i TLabel
2. Tworzymy zmienną globalną:

var
FPunkt: TPoint;

3. Tworzymy nową funkcję klasy TForm:

public
  FUNCTION GetDirection(X1, Y1, X2, Y2: Integer): Char;
end;

i uzupełniamy ją:

FUNCTION TForm1.GetDirection(X1, Y1, X2, Y2: Integer): Char;
VAR
  absdX, dX, absdY, dY: Integer;
  absTan: Single;
BEGIN
  dX := X2 - X1;
  dY := Y2 - Y1;
  absdX := abs(dX);
  absdY := abs(dY);

  IF ((absdX < 30) AND (absdY < 30)) THEN
    Exit;
  IF absdY <> 0 THEN
    absTan := absdX / absdY
  ELSE
    absTan := High(Integer); //+nieskończoność, ustawienie możliwie maksymalnej liczby - gdy dY=0 to kąt = 90%, więc zgodnie z funkcjami trygonom.: tg(90)=+~ (zamiast TRY .. EXCEPT)
  IF (absTan < 1) THEN
    BEGIN
      IF (dY < 0) THEN
        Result := 'G'
      ELSE
        Result := 'D';
    END
  ELSE
    BEGIN
      IF (dX < 0) THEN
        Result := 'L'
      ELSE
        Result := 'P';
    END;
  FPunkt.X := X2;
  FPunkt.Y := Y2;
END;

4. TPanel.OnMouseDown:

begin
  FPunkt.X := X;
  FPunkt.Y := Y;
end;

5. TPanel.OnMouseUp:

begin
  Label1.Caption := '';
end;

6. TPanel.OnMouseMove:

VAR
  FChar: Char;
BEGIN
  IF ssRight IN Shift THEN
    BEGIN
      FChar := GetDirection(FPunkt.X, FPunkt.Y, X, Y);
      WITH Label1 DO
        IF Length(Caption) > 0 THEN
          BEGIN
            IF FChar <> Caption[Length(Caption)] THEN
              Caption := Caption + FChar;
          END
        ELSE
          Caption := Caption + FChar;
      Application.ProcessMessages;
    END;
END;

1 użytkowników online, w tym zalogowanych: 0, gości: 1