AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi WndProc bei Programmen im Hintergrund
Thema durchsuchen
Ansicht
Themen-Optionen

WndProc bei Programmen im Hintergrund

Ein Thema von UliBru · begonnen am 4. Jul 2013 · letzter Beitrag vom 8. Jul 2013
Antwort Antwort
Seite 1 von 2  1 2      
UliBru

Registriert seit: 10. Mai 2010
155 Beiträge
 
Delphi 11 Alexandria
 
#1

WndProc bei Programmen im Hintergrund

  Alt 4. Jul 2013, 15:25
Hi,

ich hab da in einem Programm folgenden Code, um z.B. Play und Stop per Fernbedienung zu realisieren (Stichwort HID USB):
Delphi-Quellcode:
type
  TMainForm = class(TForm)
    ...
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    procedure StopMyPlayback;
    procedure StartMyPlayback;
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.WndProc(var Message: TMessage);
const
  FAPPCOMMAND_MASK = $F000;
var
  cmd: integer;
begin
  inherited;
  if (Message.Msg = WM_APPCOMMAND) then
  begin
    cmd := Message.LParamHi and not FAPPCOMMAND_MASK;
    case cmd of
      APPCOMMAND_MEDIA_STOP: StopMyPlayback;
      APPCOMMAND_MEDIA_PLAY: StartMyPlayback;
    end;
  end;
end;
Das läuft soweit. Aber nur, solange das Programm in Vordergrund aktiv ist.
Was ist zu tun, damit es auch startet und stoppt, wenn das Prog minimiert ist?
Wo finde ich vielleicht ein Beispiel?

Ich ahne bereits, dass da irgendein gewaltiger zusätzlicher Overhead nötig wird (Hook, dll etc.), aber vielleicht geht es doch ganz einfach.

Uli
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#2

AW: WndProc bei Programmen im Hintergrund

  Alt 4. Jul 2013, 17:30
Du könntest dich in die Messageloop der Applikation einklinken:
Delphi-Quellcode:
procedure TMainForm.HandleOnMessage(var Msg: TMsg; var Handled: Boolean);
begin
  // Vorsicht! hier rauschen ALLE Messages der Anwendung durch
  // Debuggen ist schwierig weil jede Bewegung des Mauszeigers neu Messages auslöst
  
  if Msg.Message = WM_APPCOMMAND then
  begin
...
  end;
end;

...
procedure TMainForm.FormCreate(Sender:TObject);
begin
  Application.OnMessage := self.HandleOnMessage;
fork me on Github
  Mit Zitat antworten Zitat
UliBru

Registriert seit: 10. Mai 2010
155 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: WndProc bei Programmen im Hintergrund

  Alt 4. Jul 2013, 19:36
Ich hab das mit dem HandleOnMessage probiert, es klappt aber nicht.
Wenn ich anstelle von
  if Msg.Message = WM_APPCOMMAND then testweise einmal   if Msg.Message = WM_KEYDOWN then verwende und mir dazu eine Testausgabe mache, dann klappt es.
D.h. dass also das WM_APPCOMMAND im HandleOnMessage anscheinend nicht ankommt.

Uli
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...
  Mit Zitat antworten Zitat
UliBru

Registriert seit: 10. Mai 2010
155 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: WndProc bei Programmen im Hintergrund

  Alt 4. Jul 2013, 19:49
Eine weitere Feststellung:
Beim Tastendruck auf die Fernbedienung wird auch das Ereignis WM_KEYDOWN ausgelöst. Nun gut, evtl. wäre da mit einer entsprechenden Auswertung auch irgendwas darstellbar.

ABER: wenn das Programm im Hintergrund läuft, wird auch kein WM_KEYDOWN mehr verarbeitet.
Insofern hilft das Application.OnMessage auch nicht weiter. Es bekommt keine Tastatur-Message sobald das Programm nicht aktiv im Vordergrund steht.

Uli
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...
  Mit Zitat antworten Zitat
UliBru

Registriert seit: 10. Mai 2010
155 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: WndProc bei Programmen im Hintergrund

  Alt 5. Jul 2013, 12:09
Während es keine weitere Antwort mehr gegeben hat habe ich mich durch gefühlte 1001 Links zum Thema Global Hooks etc. gewühlt.

Eine Lösung habe ich bekommen mit RegisterHotkey. Dabei fängt aber dann mein Programm eben die Taste der Fernbedienung ab und andere Programme, z.B. Mediaplayer, bekommen dann die Funktion nicht mehr mitgeteilt.
Ein globales Hooken mit eigener zusätzlicher dll ist ebenfalls reichlich aufwendig.

Die Lösung, die nun genau das tut, was es soll, sieht so aus (dabei werden zwei externe Windows API-Funktionen eingebunden):
Delphi-Quellcode:
type
  TMainForm = class(TForm)
    ...
  private
    ShellHookMessage: Integer;
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    procedure StopMyPlayback;
    procedure StartMyPlayback;
  end;

var
  MainForm: TMainForm;

function RegisterShellHookWindow(hWnd: hWnd): boolean; stdcall; external 'User32.dllname 'RegisterShellHookWindow';
function DeregisterShellHookWindow(hWnd: hWnd): boolean; stdcall; external 'User32.dllname 'DeregisterShellHookWindow';

implementation

{$R *.dfm}

procedure TMainForm.WndProc(var Message: TMessage);
const
  FAPPCOMMAND_MASK = $F000;
var
  cmd: integer;
begin
  inherited;
  if (Message.Msg = ShellHookMessage) and (Message.WParam = HSHELL_APPCOMMAND) then
  begin
    cmd := Message.LParamHi and not FAPPCOMMAND_MASK;
    case cmd of
      APPCOMMAND_MEDIA_STOP: StopMyPlayback;
      APPCOMMAND_MEDIA_PLAY: StartMyPlayback;
    end;
  end;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  DeregisterShellHookWindow(Handle);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  ShellHookMessage := RegisterWindowMessageA('MYSHELLHOOK');
  RegisterShellHookWindow(Handle);
end;
Damit kommen die Kommandos der Fernbedienung an, egal ob das Programm im Vorergrund ist oder nicht. Und die Kommandos werden auch an andere Programme weitergereicht (so sie es denn sollen).

Vielleicht hilft der Code ja auch mal anderen.

Uli
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#6

AW: WndProc bei Programmen im Hintergrund

  Alt 8. Jul 2013, 03:22
RegisterWindowMessageA('MYSHELLHOOK'); 'MYSHELLHOOK' ist auch nicht so toll. Da gibt es bestimmt einige. Nimm eine GUID und du bist auf der sicheren Seite.

Ich würde noch prüfen, ob RegisterShellHookWindow nicht fehl geschlagen ist.
Michael
Ein Teil meines Codes würde euch verunsichern.

Geändert von Luckie ( 8. Jul 2013 um 03:25 Uhr)
  Mit Zitat antworten Zitat
UliBru

Registriert seit: 10. Mai 2010
155 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: WndProc bei Programmen im Hintergrund

  Alt 8. Jul 2013, 08:24
Nimm eine GUID und du bist auf der sicheren Seite.

Ich würde noch prüfen, ob RegisterShellHookWindow nicht fehl geschlagen ist.
Danke. Mit GUID bin ich einverstanden.

Müsste denn ein optimierter Code nicht in etwa so aussehen?
Delphi-Quellcode:
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if shellHookWindowRegisteredSuccessfully then
    DeregisterShellHookWindow(Handle);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  ShellHookMessage := RegisterWindowMessageA(myGUID);
  if ShellHookMessage <> 0 then
    shellHookWindowRegisteredSuccessfully := RegisterShellHookWindow(Handle);
  if not shellHookWindowRegisteredSuccessfully then
    MachIrgendeineFehlerbehandlung;
end;
Ansonsten, wenn RegisterShellHookWindow fehlschlägt, dann findet ja schlichtweg das WndProc mit Message.Msg = ShellHookMessage nicht statt. MachIrgendeineFehlerbehandlung dient dann nur dazu, den Anwender gezielt zu informieren.

Eine generelle Frage, vermutlich einen eigenen Thread wert: man findet x Beispiele, welche die Funktionsergebnisse von API-Aufrufen nicht auswerten. Was ist besser: trotzdem auswerten und das Programm mit Fehlerauswertungen aufblähen oder doch auch ab und zu das Ignorieren von Funktionsergebnissen zulassen? Klar ist, dass das erstere das sicherere Verfahren ist.
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.622 Beiträge
 
Delphi 12 Athens
 
#8

AW: WndProc bei Programmen im Hintergrund

  Alt 8. Jul 2013, 08:54
Was ist besser: trotzdem auswerten und das Programm mit Fehlerauswertungen aufblähen oder doch auch ab und zu das Ignorieren von Funktionsergebnissen zulassen?
Es geht ja nicht in erster Linie um Fehlermeldungen, sondern darum, dass man ggf. mit einer Funktionsrückgabe (z.B. einem Handle) weiterarbeitet. Da wäre es doch sinnvoll, erst zu prüfen, ob diese Daten auch gültig sind. Was man im Fehlerfall tut, hängt ja vom Einzelfall ab, evtl. kann man das auch kaltlächelnd ignorieren.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
UliBru

Registriert seit: 10. Mai 2010
155 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: WndProc bei Programmen im Hintergrund

  Alt 8. Jul 2013, 09:06


Das Handle in RegisterShellHookWindow(Handle) ist kein Rückgabewert sondern ein Eingabewert, hier also das Handle des Programms (ich glaube Self.Handle wäre in diesem Fall dasselbe). Der Rückgabewert der API-Funktion ist boolean und zeigt lediglich an, dass die Registrierung erfolgreich war.
Siehe auch http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

Der eigentlich verwendete Rückgabewert ist im gegebenen Fall die Variable ShellHookMessage, die in WndProc verwendet wird.
Er wollte so richtig in Delphi einsteigen. Nun steckt er ganz tief drin ...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.622 Beiträge
 
Delphi 12 Athens
 
#10

AW: WndProc bei Programmen im Hintergrund

  Alt 8. Jul 2013, 09:13
Erst kündigst Du eine generelle Frage an, und dann beziehst Du Dich doch auf das spezifische Problem?
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz