Symulacja Drag and Drop

0

Witam
Jak można symulować drag and drop.
Chciałbym wydarzeniem ButtonClick lub uruchomieniem skrótu klawiaturowego spowodować przesunięcie zawartości okna przeglądarki (konkretnie mapy tak jak w google.maps) o pewną odległość (z punktu x1,y1 do x2,y2). Czyli symulacja przesuwania kursora z symulowanym wciśnięciem lewego przycisku i następnie puszczenie.
Czy w mouse_event są odpowiednie polecenia. Znam symulację naciśnięcia i puszczenia lewego przycisku ale przecież pomiędzy nimi ma być przesunięcie- jak wykonać to przesunięcie :)

0

Próbowałem kod:

  CurPos,Pt : TPoint;
begin
  GetCursorPos(CurPos);
  Application.ProcessMessages;
  {Get the point in the center of Button 2}
  Pt.x := CurPos.X ;
  Pt.y := CurPos.Y ;
  {Convert Pt to screen coordinates and Mickeys}
  Pt := ClientToScreen(Pt) ;
  Pt.x := Round(Pt.x * (65535 / Screen.Width)) ;
  Pt.y := Round(Pt.y * (65535 / Screen.Height)) ;

  {Simulate the left mouse button down}
  Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, Pt.x, Pt.y, 0, 0) ;;

  {Simulate the mouse move}
  Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE, Pt.x+400, Pt.y+400, 0, 0) ;

  {Simulate the left mouse button up}
  Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, Pt.x+400, Pt.y+400, 0, 0) ;

ALE PRZESUWA TYLKO KURSOR A NIE TO CO POD KURSOREM :(

0

Nie wiem jak zrobić żeby w czasie przesuwania kursora Lewy Przycisk Myszy pozostawał cały czas wciśnięty........

0

Ja mam taką aplikację, która klika w wyznaczony punkt kod wygląda tak:

var
  CurrentPos : TPoint;
  CurrentWindow : HWND;
begin
  CurrentWindow := GetForegroundWindow; // pobierz uchwyt aktywnego okna
  GetCursorPos(CurrentPos); // pobierz tymczasowa pozycje ekranu

  ShowWindow(Foreground, SW_SHOWNA);  // pokaz okno
  BringWindowToTop(Foreground); // dla pewnosci - wysun na wierzch
  SetForegroundwindow(Foreground);  // ustaw aktywne okno

  //Xedt i Yedt to TEdit z zapisanymi współrzędnymi gdzie kliknąć więc u ciebie załatwi to GetCursorPos
  SetCursorPos(StrToInt(Xedt.Text), StrToInt(Yedt.Text));  // ustaw w wybranej pozycji
  { kliknij na pozycje }
  mouse_event(MOUSEEVENTF_LEFTDOWN, StrToInt(Xedt.Text), StrToInt(Yedt.Text), 0, 0);
  //tu dorabiasz mouse move 
...
  //i na końcu up
  mouse_event(MOUSEEVENTF_LEFTUP, StrToInt(Xedt.Text), StrToInt(Yedt.Text), 0, 0);

  ShowWindow(Currentwindow, SW_SHOWNA);  // pokaz okno
  SetForegroundWindow(Currentwindow);  // ustaw aktywne okno
  SetCursorPos(CurrentPos.X, CurrentPos.Y); // ustaw ponownie na poprzedniej pozycji
end;
1

Zaposnaj się z tym wątkiem bo też miałem kiedys podobny problem :) Ty po prostu będziesz musiał wyświetlać część mapy albo wczytywac tylko okreslony jej fragment po przesunięciu.

http://4programmers.net/Forum/Delphi_Pascal/268338-przesuwanie_obrazka_po_canvas

0

Karpov, dziękuję za przykład, z tym że mnie chodzi nie o samo drag&drop ale o jego symulację, czyli efekt przesunięcia ma być wywołany nie ruchem myszki z wciśniętym przyciskiem tylko np. skrótem klawiaturowym.

Z klawiatury ma być uruchomiony kod symulujący ruch myszy z wciśnięciem lewego przycisku.

Nie potrzebuję sprawdzać czy obiekt pod kursorem nadaje się do przesuwania, bo wiem że tak (nad takim obiektem ustawiam kursor)

0

Podobną zabawę urządziłem sobie ostatnio podczas pisania "sterownika" dla gamepada dla gry agar.io; Program cyklicznie sprawdzał stan D-Pada oraz jego przycisków, na tej podstawie ustawiał kursor w odpowiednim miejscu na ekranie, a także symulował wciskanie i puszczanie klawiszy W, Space, Esc itd.; Program był bardziej skomplikowany, dlatego że dodatkowo umożliwiał obsługę dwóch trybów (gry oraz obsługi menu); W tym drugim trybie, D-Padem możliwe było poruszanie kursorem po ekranie, a przycisk umożliwiał symulację klikania LPM;

Symulacja ruchu kursorem to pobieranie jego pozycji za pomocą GetCursorPos, modyfikacja współrzędnych względem danego kierunku oraz ustawienie kursora na nowej pozycji za pomocą SetCursorPos; Symulacja wciskania przycisków myszy to wywołania mouse_event, a klawiszy klawiatury to wywołania keybd_event;

Jeśli więc potrzebujesz zasymulować drag & drop to wystarczą:

  • GetCursorPos i SetCursorPos do ruchu kursorem,
  • mouse_event do symulacji wciśnięcia i puszczenia LPM;
    Zamiast mouse_event i keybd_event można skorzystać z SendInput; Schemat jest względnie prosty:
  1. ustawienie kursora w miejscu początkowym,
  2. symulacja wciśnięcia LPM,
  3. w pętli, względem kierunku i odległości:
  4. pobranie bieżącej pozycji kursora,
  5. modyfikacja współrzędnych według zadanego kierunku i odległości,
  6. ustawienie kursora w nowej pozycji,
  7. zamrożenie pętli na chwilkę,
  8. symulacja puszczenia LMP;
    Teraz wystarczy to zapisać w postaci kodu;

Przesuwanie kursora poziomo, pionowo oraz po ukosach jest proste, bo wystarczy dodać lub odjąć rozmiar skoku od danej współrzędnej/współrzędnych; Nieco trudniej jest przesuwać kursor dla zadanego kąta, jednak algorytm wyznaczania nowego punktu na podstawie zadanego kąta i odległości jest bardzo prosty; Ten sam algorytm używany jest do rysowania linii - można go znaleźć w sieci bez problemu.

0

furious programming , tego się nie spodziewałem
muszę to sprawdzić, działa czy nie działa

0

Na pewno będzie działać, dlatego że dla systemu to wszystko jedno, czy użytkownik steruje prawdziwą myszą, czy aplikacja ją udaje; Efekt podanego przeze mnie rozwiązania będzie wyglądał tak, jakby kursor sam chodził po ekranie i robił to co mu się podoba :]

0

urious programming ,jestem w trakcie tworzenia, lecz są małe trudności
1-nie rozumiem dlaczego jest potrzebna pętla , czyżbym musiał przesuwać piksel po pikselu?,
a nie mogę po prostu podać jedynie początkowe a potem końcowe położenie kursora (skoro potrzebuję tylko jedno przesunięcie z punktu a do b po prostej)?
2-po co w trakcie przesuwania pobierać pozycję kursora (przecież ustawiam go poleceniem SetCursorPos więc wiadomo gdzie on jest-przecież nigdzie nie powędrował)
3-a jeśli już konieczna pętla i jej chwilowe zamrożenie to jak wykonać zamrożenie

0

1-nie rozumiem dlaczego jest potrzebna pętla , czyżbym musiał przesuwać piksel po pikselu?,
a nie mogę po prostu podać jedynie początkowe a potem końcowe położenie kursora (skoro potrzebuję tylko jedno przesunięcie z punktu a do b po prostej)?

Oczywiście że możesz - to co podałem umożliwi stworzenie animacji ruchu kursora, jednak jeśli nie potrzebujesz ładnego wizualnie efektu to możesz od razu przenieść kursor z punktu źródłowego do docelowego; Powinno bez problemu działać;

2-po co w trakcie przesuwania pobierać pozycję kursora (przecież ustawiam go poleceniem SetCursorPos więc wiadomo gdzie on jest-przecież nigdzie nie powędrował)

To dotyczy animacji, więc punkt ten możesz pominąć; Zresztą nawet przy animowanym ruchu kursora, wystarczy dodatkowa zmienna z bieżacą pozycją, aby wykluczyć pobieranie pozycji przez GetCursorPos w pętli;

3-a jeśli już konieczna pętla i jej chwilowe zamrożenie to jak wykonać zamrożenie

Wystarczy samo Sleep, ew. dodatkowo Application.ProcessMessages, jeśli podczas ruchu kursora kolejka komunikatów ma być przetwarzana "w tle";

Trochę się zagalopowałem z poprzednim opisem, bo miałem w głowie animację i na tej podstawie opisałem rozwiązanie; Jeżeli nie chcesz animacji to schemat będzie dużo prostszy:

  1. ustawienie kursora w punkcie źródłowym, za pomocą SetCursorPos,
  2. symulacja wciśnięcia LPM np. za pomocą mouse_event,
  3. ustawienie kursora w punkcie docelowym, za pomocą SetCursorPos,
  4. symulacja puszczenia LPM np. za pomocą mouse_event;
    Być może mały Sleep będzie potrzebny, aby aplikacja zdążyła zareagować na przeciąganie.
0

Napisałem maksymalnie prosty kod na próbę:

procedure TForm1.Button1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  SetCursorPos(20,140);
  Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN,20,140, 0, 0) ;
  SetCursoRPos(150,140);
  Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP,150,140, 0, 0) ;
end;

Próbowałem przesunąć ikonę na pulpicie W7 :zaznacza ikonę a kursor przesuwa się w prawo o te 130 pikseli, ale ikona pozostaje tam gdzie była. (Jeżeli wykonuję to myszą po tej samej drodze to ikona zostaje przesunięta)
Próba przesuwania mapy na stronie google.pl też bez powodzenia.
Spróbuję dodać sleep(200);

0

W razie czego spróbuj z animacją.

0

Po dodaniu sleep (pomiędzy SetCursorPos a puszczeniem przycisku) działa z ikonami na pulpicie (przesuwa prawidłowo).
Online z mapami w google .pl nadal nie działa.
To co uzyskałem to i tak dużo, przynajmniej dobry kierunek.
Jednak zależy mi na przesuwaniu mapy w google.
Na razie jeszcze popróbuję dołożyć więcej sleep()-ów.

0

Czy ta mapa jest w twojej aplikacji? Jeśli tak może zabierasz się do problemu od złej strony. Nigdy się tym nie bawiłem ale może niepotrzebnie wyważasz otwarte drzwi - opisz czego używasz do jej wyświetlania, jakiego api itp.

0

Na razie jeszcze popróbuję dołożyć więcej sleep()-ów.

Po każdym Sleep daj Application.ProcessMesages - to może mieć znaczenie.

0

Mapa nie jest w mojej aplikacji tylko w przeglądarce internetowej

Ale tym razem lepsze wieści:
Z samym tyko sleep przesuwa pięknie mapy w innych witrynach niż google (w google nie chce , ale pal go licho- zostawię dalsze eksperymenty na później - (np próbę dodania Application.ProcessMesages) ).
Na razie zadowolę się korzystaniem z map na innych serwisach niż google.
W sumie sukces:)
Wielkie Dzięki

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