Thema: Delphi Multimedia-Tasten hooken

Einzelnen Beitrag anzeigen

Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
900 Beiträge
 
Delphi 11 Alexandria
 
#1

Multimedia-Tasten hooken

  Alt 16. Feb 2006, 16:11
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:
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;
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: *klick*)
Mein Hook-Code sieht so aus:
Delphi-Quellcode:
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;
Dabei benutze ich diese Unit, um sehr einfach ein MMF zu erstellen (oDemoObj ist von dieser Kalsse abgeleitet und hat die Eigenschaften MainWindow und HookHandle).

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).
  Mit Zitat antworten Zitat