MouseHook przechwycenie ruchu myszki

0

Witajcie koledzy,
mam formatka na niej pewnie komponenty porozciągane na cały obszar.
Chciałbym coś wykonać jeśli wystąpi ruch na formatce.
Oprogramowałem więc zdarzenie OnMouseMove formatki - nie działało.

Myślę sobie pewnie muszę dać OnMouseMove na komponencie, ktory lezy na formatce - działa, ale byle jak.w momencie uruchomienia aplikacji, gdy nic się z myszką nie dzieje, komponent wywoluje samoczynnie co kilka milisekund OnMouseMove.

Porzucilem wiec te zdarzenie i probuje napisac malego hooka na myszke, ktory wyswietli mi showmessage('ruch') jeden raz a potem sie wyrejestruje.

Macie pomysly? Prosilbym o jakis przyklad. Dzieki

0

Oprogramowałem więc zdarzenie OnMouseMove formatki - nie działało.

Działa:

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  ptMouse: TPoint;
begin
  GetCursorPos(ptMouse);
  ptMouse := ScreenToClient(ptMouse);
  lblPosX.Caption := IntToStr(ptMouse.X);
  lblPosY.Caption := IntToStr(ptMouse.Y);
end;

FormMouseMove.png


Myślę sobie pewnie muszę dać OnMouseMove na komponencie, ktory lezy na formatce - działa, ale byle jak.w momencie uruchomienia aplikacji, gdy nic się z myszką nie dzieje, komponent wywoluje samoczynnie co kilka milisekund OnMouseMove.

Bzdura - nic takiego się nie dzieje; To by żadnego sensu nie miało, jeśli kilkaset razy na sekundę wysyłane były by zbędne komunikaty;

Jeśli uruchomię aplikację i dokładnie pod kursorem pokaże się formularz, to komunikat o zmianie położenia kursora myszy zostanie wysłany tylko jeden raz; Przykład:

procedure TForm1.lbMousePosMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  ptMouse: TPoint;
begin
  GetCursorPos(ptMouse);
  ptMouse := ScreenToClient(ptMouse);
  lbMousePos.Items.Add(Format('%d, %d', [ptMouse.X, ptMouse.Y]));
end;

ListBoxMouseMove.png

Uruchamiałem z pięćdziesiąt razy program w ten sposób i zawsze w kontrolce pojawiał się tylko jeden item (z aktualną pozycją kursora w oknie);


Wniosek: Byle jak napisałeś kod, to byle jak działa; Poza tym nawet nie byłeś łaskaw go przedstawić, więc nic więcej napisać nie mogę; Zdarzenia działają bardzo dobrze, problem leży gdzie indziej (dokładnie pomiędzy monitorem a krzesłem).

0

No ładny post, ale kolokwialny.

procedure TForm.VideoMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
   Showmessage('ruch');
end; 

komponent video to FiltrGraph z pakietu DSPACK.

Położyć sobie na formę listboxa to i ja potrafię i pewnie będzie działać onmousemove jak zazwyczaj działało.
Tutaj opisałem wyraźnie, że coś nie gra.

0

Położyć sobie na formę listboxa to i ja potrafię i pewnie będzie działać onmousemove jak zazwyczaj działało.
Tutaj opisałem wyraźnie, że coś nie gra.

Zamiast cwaniakować trzeba było od razu napisać, że to komponent ten i ten; A tak to ani w temacie , ani w treści wątku, ani w jego tagach nie byłeś łaskaw napisać o który konkretnie chodzi, więc podałem przykład dla pierwszego z brzegu;

Skoro kontrolka fałszywie wysyła komunikaty to podejżewam, że taka sama sytuacja będzie miała miejsce w normalnym hooku na mysz (o szczegóły pytaj @olesio ); Ja nie mam tej paczki zainstalowanej i nie będę jej instalować, więc nie pomogę.

0

Może nie napisałem wszystkiego dokładnie, ale próbę wmówienia mi, że nie wiem jak działa OnMouseMove i posłużenie się marnym listboxem odebrałem lekko obraźliwie :)

Tak czy siak można powiedzieć, że pomogłeś bo zrezygnowałem z OnMouseMove oraz hooka, wstawiłem timera, ktory porownuje wspolrzędne myszki i sprawa rozwiązana.

pozdrawiam

0

Myślę, że hook by działał, ale musiałbym z tym sporo pokombinować, a w temacie hooków nie jest nie bieżąco, a nie udało mi się znaleźć w dość ograniczonym czasie, żadnego
fajnego przykładu..

0

Moglby ktos sprawdzic tego linka od noname_l, bo u mnie na win7 nie za bardzo chce dzialac?

(jak ktos ma czas, bo sprawa już jest i tak powyzej rozwiazana)

0

Co sprawdzić Hooka? Przecież to marnowanie czasu skoro aplikacja a dokładnie jej okno dostaje jakieś "dziwne" komunikaty to jak założysz hooka nagle ich nie będzie? Jeżeli naprawdę myszką nikt nie ruszył a komunikat wystąpił (było by to bardzo dziwno zjawisko) co za problem zapisać do jakiejś zmiennej ostanie położenie myszki a później w obsłudze tego komunikatu sprawdzać czy się zmieniło jeżeli tak to coś tam robisz.

0

@bonzo12x: jeżeli potrzebujesz hook globalny na muszkę, to raczej powinno się go zakładać z parametrem WH_MOUSE_LL. Jaka jest różnica między tym, a innym w artykule, do którego podał link @kAzek - możesz wyczytać na MSDN pod hasłem "hooks overview". Natomiast Hook Ci może nie działać, tylko jeżeli masz włączone UAC (albo zrobiłeś coś nie tak w swoim kodzie).

Rozwiązanie to uruchomić program na prawach admina / dodać odpowiedni manifest do zasobów, który wymusi takie uruchomienie / wyłączyć UAC (osobiście stosuje te rozwiązane, ale jak ktoś woli upierdliwe komentarze albo nie myśli co robi podczas używania systemu, to lepiej niech nie rusza). Więcej informacji do wygoologwania na mnóstwie stron. Poniżej zamieszczam wycinek działającego kodu, pokazującego jak założyć, obsłużyć i zdjąc globalny hook na myszkę.

//...
var
  MainForm : TMainForm;
  MouseHookHandle : HHOOK;

const
  WH_MOUSE_LL = $0E;
  InOut_Arr : array[boolean] of string = ('Out', 'In');

implementation

{$R *.dfm}

function IsPointInForm(Pt : TPoint; AForm : TForm) : boolean;
begin
  Result := PtInRect(AForm.BoundsRect, Pt);
end;

function LocalMouseHookProc(Code : integer; WParam : WPARAM; LParam : LPARAM) : LRESULT; stdcall;
var
  HookStruct : PMOUSEHOOKSTRUCT;
begin
  HookStruct := Pointer(LParam);
  case Code of
    HC_ACTION :
      begin
        MainForm.Caption := InOut_Arr[IsPointInForm(HookStruct.Pt, MainForm)];
      end
  end;
  Result := CallNextHookEx(MouseHookHandle, Code, WParam, LParam);
end;

procedure TMainForm.FormClose(Sender : TObject; var Action : TCloseAction);
begin
  if MouseHookHandle > 0 then
  begin
    UnhookWindowsHookEx(MouseHookHandle);
  end;
end;

procedure TMainForm.FormCreate(Sender : TObject);
var
  Pt : TPoint;
begin
  GetCursorPos(Pt);
  Application.Title := Caption;
  MainForm.Caption := InOut_Arr[IsPointInForm(Pt, MainForm)];
  MouseHookHandle := SetWindowsHookEx(WH_MOUSE_LL, @LocalMouseHookProc, HInstance, 0);
end;
//...

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