![]() |
Multimedia-Tasten hooken
Zuallererst: 'Tschuldigung für so ein langes Erst-Posting...
Ich möchte in meinem Programm die Benutzung der Multimediatasten einer Tastatur ermöglichen. Das mache ich so:
Delphi-Quellcode:
Das funktioniert so weit ganz gut. Da die Steuerung auch dann funktionieren soll, wenn mein Fenster nicht den Fokus hat, hab mich mal mit Hooks beschäftigt. (Das Problem habe ich übrigens im DF auch schon erläutert:
TForm1 = class(TForm)
protected procedure MediaKey (Var aMSG: tMessage); message WM_APPCOMMAND; end; //... procedure TForm1.MediaKey (Var aMSG: tMessage); begin case aMSG.LParam of APPCOMMAND_MEDIA_NEXTTRACK: begin Memo1.lines.add('Next'); aMsg.Result := 1; end; APPCOMMAND_MEDIA_PREVIOUSTRACK: begin Memo1.lines.add('Prev'); aMsg.Result := 1; end; //usw. end; end; ![]() Mein Hook-Code sieht so aus:
Delphi-Quellcode:
Dabei benutze ich
function InstallHook(Hwnd: Cardinal): Boolean; stdcall;
begin Result := False; if HookHandle = 0 then begin //Erstmal Hook installieren HookHandle := SetWindowsHookEx(WH_SHELL, @KeyboardHookProc, HInstance, 0); //Uebergebenes Fensterhandle sichern MyWindowHandle := Hwnd; oDemoObj := TWDB_IPCDemoObj.Create('NempNochEinMP3Player'); oDemoObj.MainWindow := Hwnd; oDemoObj.HookHandle := HookHandle; Result := True; showmessage('Installiert ' + inttostr(HookHandle) + ' ' + inttostr(MyWindowHandle)); end; end; function UninstallHook: Boolean; stdcall; begin Result := UnhookWindowsHookEx(oDemoObj.HookHandle); end; function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin oDemoObj := TWDB_IPCDemoObj.Create('NempNochEinMP3Player'); case nCode < 0 of FALSE: begin if (lparam = APPCOMMAND_MEDIA_NEXTTRACK) or (lparam = APPCOMMAND_MEDIA_PREVIOUSTRACK) or (lparam = APPCOMMAND_MEDIA_STOP) or (lparam = APPCOMMAND_MEDIA_PLAY_PAUSE) then begin SendMessage(oDemoObj.MainWindow,WM_APPCOMMAND,wparam,lParam); //showmessage('Abgefangen ' + inttostr(oDemoObj.HookHandle) + ' ' + inttostr(oDemoObj.MainWindow)); Result := 1; end else Result := CallNextHookEx(oDemoObj.HookHandle, nCode, wParam, lParam); end; else Result := CallNextHookEx(oDemoObj.HookHandle, nCode, wParam, lParam); end; end; ![]() Das funktioniert soweit auch - das heißt, wenn meine Anwendung den Hook installiert, dann erscheinen in der Memo der Hauptanwendung auch brav die Tastendrücke. Auch dann, wenn das Fenster nicht den Fokus hat. Aber: Ich habe bei mir auch "iTouch" laufen. Dies ist ein Tool von Logitech. Was es genau macht, weiß ich nicht. Ich vermute sehr stark, dass es ebenfalls die APPCOMMAND_MEDIA_xxx Messsages (und andere) hookt und an sämtliche andere Fenster weiterleitet, damit diese die Multimediatasten ohne eigene Hooks benutzen können. (D.h. Meine Anwendung bekommt auch ohne meinen Hook die Nachrichten, aber ich möchte nicht voraussetzen, dass überall iTouch installiert ist). Und da gibts jetzt Probleme. Wenn dieses iTouch vor meinem Hook gestartet wird (was die Regel sein dürfte), dann fängt iTouch die Message zuerst ab und sendet sie weiter, was dann von meinem Hook abgefangen wird und an meine Anwendung weitergeleitet wid. Und das passiert leider nicht nur einmal, sondern öfter (die genaue Zahl hängt von der Zahl der offenen Fenster ab). D.h. ein Druck auf die Taste Next bewirkt, dass meine Anwendung ca. 20 mal die Nachricht erhält. Das (hier auskommentierte) ShowMessage erscheint übrigens mit den entsprechenden Anwendungstiteln, die gerade laufen. Also ein paar mal "explorer", ein paar mal "delphi" usw. Die Frage ist nun, was ich da falsch mache. Und für den unwahrscheinlichen Fall, dass ich nichts falsch mache, sondern das Problem bei iTouch liegt, wie kann ich das umgehen? D.h. wie kann ich feststellen, ob die Nachrichten, die ich hooken möchte, bereits gehookt werden? Damit mein Hook nicht zusätzlich installiert wird (in der Hoffnung, dass es dann schon klappt). |
Re: Multimedia-Tasten hooken
Hi
ich hab auch mal versucht die Mediatasten zu Hooken. Dabei is mir aufgefallen, dass zwar mein Hook "abgespielt" wird aber trozdem die alte Nachricht gesendet wird! Problem scheint also zu sein das Windows oder das Logitech Programm das direkt auf Treiber-Ebene lösen! Wenn das wirklich so seien sollte kann man das mit dem Hooken gepflegt knicken ;) evtl äusert sich ja auch noch mal einer von unseren "Was-Macht-Windows-Genau"-Meistern :wink: Greetz Boombuler |
Re: Multimedia-Tasten hooken
Ich glaube Gausi aus dem DF hat da mal was gemacht mit seinem MP3 Player:
![]() Ächtz, es ist noch früh am morgen. Das bist du ja selber. :roll: :mrgreen: |
Re: Multimedia-Tasten hooken
Hab sowas auch schonmal versucht mit meiner Tastatur... Hatte dann aber net mehr die Zeit dazu das weiterzutreiben... Den Tastatur-Hook konnt ich getrost vergessen... Den hats einfach ignoriert. ^^
Hatte dann gelesen, dass es wohl mit einem Low-Level-Hook funktionieren könnte, aber um das auszuprobieren fehlte die Zeit... Vielleicht schaffst du es ja damit... ;-) |
Re: Multimedia-Tasten hooken
Es laeuft ein Service der die Multimediatasten liest. Die Multimediatasten sind naemlich zumindest bei USB-Tastaturen ein eigenstaendiges Geraet.
Dieser Service sendet das WM_APPCOMMAND und wenn es von der Applikation nicht verboten wird, dann werden die Standardbelegungen vom Service initiiert. Ungluecklicherweise koennen auch andere Programme solche Tricks ausfuehren. Wie bemerkt sind das Maustreiber oder Tastaturtreiber. Genaugenommen macht es die Tray-Applikation, die ueber einen Seitenausgang des proprietaeren Treibers mit der Maus oder Tastatur kommuniziert und all die komischen Belegungen direkt implementiert. Die Tasten gelangen nie ans Betriebssystem sondern nur an die Tray-Applikation. |
Re: Multimedia-Tasten hooken
OK, hier scheint es ja einige zu geben, die sich damit etwas auskennen :-D
Wenn ich iTouch abschalte (ob es nun die Messages hooked oder auf Treiberebene arbeitet, ist mir jetzt erstmal egal, ich klicke halt auf das Symbol im Tray und wähle "beenden"), dann funktioniert mein Hook. Wenn iTouch läuft, dann wird auch bei mehreren offenen Multimedia-Anwendungen nur eine bedient, wenn ich eine der Tasten drücke (dabei scheint es Prioritäten zu geben, der Windows-Player wird z.B bevorzugt bedient, dann kommt Winamp, dann der Thunderbird (fragt nicht, was der damit macht, ich weiß es nicht), und dann kommt meine Anwendung (ohne Hook)). Das bedeutet doch, dass iTouch mit dem Senden der Nachricht an alle Fenster aufhört, wenn eine Anwendung/ein Fenster was mit der Nachricht anfangen konnte. Wenn ich jetzt meinen Hook dazwischenschalte (d.h. alle von iTouch gesendeten Messages gehen an dieselbe Anwendung), dann wird fröhlich weitergesendet. Das legt für mich die Vermutung nahe, dass irgendwas an meiner Hook-Technik nicht richtig ist - dass nämlich die Nachricht nicht als "empfangen und erledigt" markiert wird, wenn mein Hook sie an meine Anwendung weitergeleitet hat. Am Code in der Anwendung liegt es nicht: Wenn ich zwei Instanzen meines (noch ungehookten) Players starte, erhält nur eine von iTouch die entsprechende Nachricht. @Luckie: Ja ich bins selbst :wink:. In dem mp3Player verwende ich bisher nur das erste Stück Code, was nur mit iTouch (bzw. mit Fokus) funktioniert. Ich kann es jetzt so erweitern, dass es ohne funktioniert, aber nicht so, das es auch ohne funktioniert :wall: |
Re: Multimedia-Tasten hooken
Ich bin ja eigentlich kein Freund von Schiebepostings, aber ich komme hierbei einfach nicht weiter.
Vielleicht nochmal: Die Mediatasten können ruhig erst bei iTouch oder bei sonst einem Service o.Ä. ankommen. Nur wenn dieser Service dann die Nachrichten weiterverteilt, möchte ich mit meinem Hook die Nachricht auf meine Anwendung umleiten. Das funktioniert ja auch in sofern, dass meine Anwendung die Nachricht empfängt. Nur leider empfange ich die Nachricht nicht nur einmal, sondern mehrfach, was meiner Meinung daran liegt, dass mein Hook die Nachricht nicht ganz korrekt behandelt/weiterleitet/als erledigt markiert, so dass iTouch erneut versucht, die WM_APPCOMMAND an den Mann zu bringen, was dann wiederrum von mir abgefangen und umgeleitet wird. Das geht solange, bis der Service im Hintergrund alle Fenster durchhat. Sieht denn keiner mit mehr Erfahrung als ich auf dem Gebiet den Fehler, den ich mache? |
Re: Multimedia-Tasten hooken
Hast du es bis jetzt gelöst?
Ich versuche nämlich gerade dasselbe bei meinem Mp3-Player Emat ( ![]() Nutze auch iTouch, allerdings mit eine PS2 Tastatur (ob das irgendwelche Unterschiede macht?) Wie wäre es mit einer Option in deinem Player, bei der der Anwender iTouch-Kombatibilität auswählen kann? |
Re: Multimedia-Tasten hooken
Ich habe es halbwegs lösen können, ja. Problem war, dass ohne iTouch ein Hook nötig ist (in etwa der, den ich oben gepostet habe), aber dieser Hook bei installiertem iTouch dafür sorgt, dass die Message vervielfältigt wird.
Mein Lösungsprinzip: Das Programm besitzt ein Flag "MMKey-Taste bereits benutzt", der beim Start aus einer ini gelesen wird. Initial ist dieser "False". Der Hook wird zunächst nicht installiert. Wenn das erste Mal ein MMKey-Tastendruck erkannt wird (weil z.B das Programm beim Drücken den Fokus hatte, oder iTouch läuft), dann wird ein MMKey-Test initiiert. Dieser sieht so aus, dass der Hook installiert wird, und modal ein neues Fenster geöffnet wird, was keine MMKeys empfangen kann. Der User wird dann aufgefordert, EINMAL die Play-Taste zu drücken. Im Hauptfenster wird nun (bei laufendem MMKey-Test) jede ankommende MMKey-Message "Play/Pause" registriert und dabei eine Variable hochgezählt (eine kommt mindestens an, wir haben ja den Hook installiert; zur Not gibt es ein "Abbrechen"-Button). Außerdem wird nach einem empfangenen "Play/Pause" die modale Form so geändert, dass sich beim User nett bedankt wird, und er aufgefordert wird, den OK-Button zu klicken, der dann erscheint. Dann wird die Anzahl der angekommenen Messages ausgewertet. Ist sie = 1, dann hat der Hook vernünftig funktioniert, und wird beim nächsten Mal geladen. Ist sie >1, dann ist wahrscheinlich iTouch o.Ä. installiert - auf jeden Fall läuft was schief (oder der User hat zweimal gedrückt :stupid: - für diesen Fall kann der Test auch manuell gestartet werden). Der Hook wird dann deinstalliert und beim nächsten Start nicht geladen. Der Wert "MMKey-Taste bereits benutzt" wird dann auf True gesetzt, so dass die MMKey-Einrichtung beim nächsten Mal nicht mehr durchgeführt werden muss. |
Re: Multimedia-Tasten hooken
Die von dir genutzten Konstanten habe ich im Netz gefunden:
Delphi-Quellcode:
const
APPCOMMAND_MEDIA_NEXTTRACK = $B0000; // 720896; APPCOMMAND_MEDIA_PREVIOUSTRACK = $C0000; // 786432; APPCOMMAND_MEDIA_STOP = $D0000; // 851968; APPCOMMAND_MEDIA_PLAY_PAUSE = $E0000; // 917504; Aber wie finde ich diese heraus? APPCOMMAND_VOLUME_DOWN APPCOMMAND_VOLUME_MUTE APPCOMMAND_VOLUME_UP Eine KeyDownAbfrage reagiert nicht auf die Media Tasten meiner Logitech Tastatur; die procedure MediaKey (Var aMSG: tMessage) schlägt auch nicht auf die Volume +/- Knöpfe an. Wie kann man diese in sein Programm einbinden? |
Re: Multimedia-Tasten hooken
KeyDown kann auch nichts bringen, weil diese Tasten keine Tasten im üblichen Sinne sind. Sie lösen kein Tastatur-Event aus, sondern das Senden einer WM_APPCOMMAND-Message. An die ganzen Konstanten kann man z.B. so gelangen
Delphi-Quellcode:
Man erhält dann, nach entsprechender Konvertierung ins Hex-Format:
procedure MediaKey (Var aMSG: tMessage); message WM_APPCOMMAND;
//[...] procedure TForm1.MediaKey (Var aMSG: tMessage); begin Showmessage(InttoStr(aMSG.LParam)); aMsg.Result := 1; end;
Delphi-Quellcode:
Alternativ kann man auch nach den Konstanten-Namen googeln. Irgendwo findet man immer ne Liste damit ;-)
APPCOMMAND_VOLUME_MUTE = $80000;
APPCOMMAND_VOLUME_DOWN = $90000; APPCOMMAND_VOLUME_UP = $a0000; |
Re: Multimedia-Tasten hooken
Sag mal du hookst die Tastatur-Events ?
Ich meine du müsstest bei wm_AppCommand die Fensterfunktion global hooken und nicht das Keyboard. Gruß Hagen |
Re: Multimedia-Tasten hooken
Ne, ich mach schon nen ShellHook auf WM_APPCOMMAND (vgl. Quellcode im ersten Posting). Funktioniert ja auch soweit, nur kommt der Hook mit installiertem iTouch durcheinander (iTouch scheint die Messages irgendwie mehrfach zu versenden, die dann alle vom Hook auf meine Anwendung umgelenkt werden). Daher dieser
![]() Mein Problem ist mittlerweile gelöst, nur wurde hier noch eine Frage bzgl. der anderen Konstanten gefragt. Ob das wirklich hierhin gehört, oder abgetrennt werden sollte, mag ein anderer entscheiden ;-) |
Re: Multimedia-Tasten hooken
Danke für die Info.
Aber ich habe ein Problem mit deinem Code (5. Zeile):
Delphi-Quellcode:
Delphi meckert, es brauche bei @KeyboardHookProc Parameter. Welche soll ich da angeben?
HookHandle := SetWindowsHookEx(WH_SHELL, @KeyboardHookProc, HInstance, 0);
Des weiteren vermute ich, dass man HookHandle mit 0 initialisieren muss. Richtig? Und bei InstallHook ist der Parameter hwnd = Application.Handle? Beim FormCreate ausführen? |
Re: Multimedia-Tasten hooken
ich muss das nochaml rauskramen von vor jahren :roll:
ich hab das alles probiert, aber es hilft nichts, nix klappt... ich glaub bei den toshiba notebooks (ich brauch das ja für mein notebook, das multimedia tasten drauf hat) funktioniert das nur über bibliotheken!!?? weiß einer rat wie ich die ansprechen kann?? zuständig müsste dafür tfncky.exe (toshiba controls) sein!!! es reagiert definitiv nicht auf app_command, und auch nicht auf die dierekten messages für die jeweiligen tasten... ich komm einfach nicht weiter... :cry: |
Re: Multimedia-Tasten hooken
Ich komme bei dem Thema mehr und mehr zu der Ansicht, dass hier jede Hersteller von Tastaturen/Treibern sich da ein eigenes Süppchen zusammenkocht. Bei meiner alten Logitech-Tastatur klappen die Multimediatasten gut ohne Hook im eigenen Programm, auf meinem Thinkpad brauche ich den Hook dafür. Bei der Logitech-Software für die neuen Tastaturen gibts komische Probleme, die ich noch nicht genau verstanden habe. Wie das jetzt bei Toshiba aussieht, weiß ich nicht.
Eine ultimative Lösung dafür scheint es nicht zu geben. |
Re: Multimedia-Tasten hooken
ja aber das bei toshiba muss ich sagen sieht echt schlimm aus, ich hab kein plan wie die das übermitteln mit den funktionen, oder die haben noch komplett andere messages die ich noch gar nicht erkannt hab... das ist zum mäuse melken, naja hab sie erstmal angeschrieben ob sie dafür nicht ne sdk haben, für das toshiba controls programm
|
Re: Multimedia-Tasten hooken
Zitat:
mfg, Philipp |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz