Globalny hook na klawiaturę i mysz powoduje dziwne ich zachowanie

0

Pisze sobie z kolegą śmieszny program (chcemy podesłać koledze ;)), który wydaje dźwięki przy ruszeniu klawiaturą lub naciśnięciu klawisza.
Oto funkcja odpowiedzialna za obsługę hooka

procedure MKHook(code: Integer;wparam: wParam;lparam: lParam); stdcall;
var
hook: HHOOK;
begin
    PlaySound('dzwiek.wav');
    CallNextHookEx(hook,code,wparam,lparam);
end;

Podczas ładowania formularza, zakładany jest hook

procedure TForm6.FormCreate(Sender: TObject);
begin
  MH := SetWindowsHookEx(WH_MOUSE_LL,@MouseKeyboardHook,hInstance,0);
  GH := SetWindowsHookEx(WH_KEYBOARD_LL,@MouseKeyboardHook,hInstance,0);
end;

(gdzie MH i GH to zmienne typu HHOOK)
Przy wyładowywaniu formy, hooki są zdejmowane

procedure TForm6.FormDestroy(Sender: TObject);
begin
    UnhookWindowsHookEx(MH);
    UnhookWindowsHookEx(GH);
end;

Problem jest w tym, że program czasami "dziwnie" się zachowuje, np:

  • Mysz i klawiatura przestają działać podczas uruchomienia programu (można odzyskać sterowanie za pomocą ctrl + alt + del, wcześniej coś takiego nie występowało)
  • Niektóre klawisze przestają działać na jakiś czas (np ctrl, tab, etc)
  • Niektóre klawisze zmieniają działanie, np strzałka w górę obraca ekran oO

Wie ktoś o co chodzi i jak to naprawić? ;)

0

Sorry zapomniałem, że zamiast

procedure TForm6.FormCreate(Sender: TObject);
begin
  MH := SetWindowsHookEx(WH_MOUSE_LL,@MouseKeyboardHook,hInstance,0);
  GH := SetWindowsHookEx(WH_KEYBOARD_LL,@MouseKeyboardHook,hInstance,0);
end;

ma być

procedure TForm6.FormCreate(Sender: TObject);
begin
  MH := SetWindowsHookEx(WH_MOUSE_LL,@MKHook,hInstance,0);
  GH := SetWindowsHookEx(WH_KEYBOARD_LL,@MKHook,hInstance,0);
end;

To tylko mały błąd, merytoryczny, który może wpłynąć na waszą interpretację, w kodzie jest właśnie tak i dalej dzieje się to samo, tu tylko zapomniałem zmienić starej nazwy funkcji na nowej, ale w oryginale wszystko jest tak samo, tj ten błąd w nazwie funkcji nie jest w tej sprawie istotny

0

Jeszcze jak byś ujawnił ciało procedury MKHook...

0
marogo napisał(a):

Jeszcze jak byś ujawnił ciało procedury MKHook...

Jest na początku opisane:

procedure MKHook(code: Integer;wparam: wParam;lparam: lParam); stdcall;
var
hook: HHOOK;
begin
    PlaySound('dzwiek.wav');
    CallNextHookEx(hook,code,wparam,lparam);
end;
2

Ja nie mam teraz wygodnego dostępu do swoich źródeł, ale poszukaj wielokrotnie wałkowanego tematu z moim załącznikiem i przykładem globalnego hooka na klawiaturę. Poczytaj też opis z MSDN, bo na 100000% Hooki te obsługiwane są w funkcji, a nie procedurze. I choćby to jest pierwszym dużym błędem.

Edit: nie moge znaleźć jak nazwałem ten załącznik i po nim posta tutaj, więc póki co masz mój kod do starszej wersji pliginu do XMPlay, tam sobie możesz zobaczyć jak wygląda działający hook i można sterować XMPlayem przy użyciu klawiszy multimedialnych. A poza tym zamiast PlaySound polecam bass.dll lub jeśli już robisz to tą funkcją, to lepiej w wątku, bo odtwarzanie dźwięku będzie niepotrzebnie wstrzymywać klawiaturę.

1
CaptchaFriend napisał(a):
marogo napisał(a):

Jeszcze jak byś ujawnił ciało procedury MKHook...

Jest na początku opisane:

procedure MKHook(code: Integer;wparam: wParam;lparam: lParam); stdcall;
var
hook: HHOOK;
begin
    PlaySound('dzwiek.wav');
    CallNextHookEx(hook,code,wparam,lparam);
end;

Upps..faktycznie, jakoś nie zauważyłem wcześniej, za dużo siedzenia przy kompie :D

Dla myszy i klawiatury powinny być osobne funkcje (a nie procedury) przetwarzające ich komunikaty.

function MouseHook(code: Integer; wparam: wParam; lparam: lParam): integer; stdcall;
begin
  PlaySound('dzwiek.wav');
  Result := CallNextHookEx(MHook, code, wparam, lparam);
end;

function KeybHook(code: Integer; wparam: wParam; lparam: lParam): integer; stdcall;
begin
  PlaySound('dzwiek.wav');
  Result := CallNextHookEx(KHook, code, wparam, lparam);
end;

procedure TForm6.FormCreate(Sender: TObject);
begin
  MHook := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, hInstance, 0);
  KHook := SetWindowsHookEx(WH_KEYBOARD_LL, @KeybHook, hInstance, 0);
end;

procedure TForm6.FormDestroy(Sender: TObject);
begin
  UnhookWindowsHookEx(MHook);
  UnhookWindowsHookEx(KHook);
end;


0

Po co osobne skoro robią to samo?
Za to PlaySound zajmuje prawdopodobnie za dużo czasu i lepiej jakby się znalazło obsłużone w osobnym wątku - funkcje wewnątrz hooka powinny być natychmiastowe; jeżeli chcesz odtworzyć jakiś dźwięk to po prostu w obsłudze zapamiętaj że trzeba go odtworzyć a w pętli głównej programu go odtwórz

0

No rzeczywiście, z tych linków poniżej wynika, że wszystko jest bez różnicy. To po co pytać na forum jeżeli wie się lepiej od Microsoftu i dokumentacji na MSDN?
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644985(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644986(v=vs.85).aspx

0

Miałem napisać, że PlaySound blokuje wszystko, ale ktoś mnie uprzedził ;)

0

Problem rozwiązany, jak pisał @olesio, nie powinienem tego robić w procedurze tylko w funkcji (dziw, że w procedurze w ogóle działało)
Hmm, u mnie PlaySound spowalnia minimalnie komputer

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