Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi WndProc in Komponente (https://www.delphipraxis.net/130087-wndproc-komponente.html)

Angel4585 3. Mär 2009 06:52


WndProc in Komponente
 
Hallo,

ich baue einen Scheduler der einmal alle 5 Minuten ein Ereignis auslösen soll und dann auch noch auf den Systemshutdown reagieren soll. Ich habe eine Komponente von TTimer abgeleitet und wollte jetzt eine WndProc verwenden, allerdings heisst es wenn ich die überschreiben will dass TTimer keine hätte.
Muss ich das anders lösen? Wenn ja, wie?

:angel:

Edit:
Die Komponente soll in einem Dienst verwendet werden, kann es da Probleme mit Windowsmessages geben?
Die OnShutdown Methode genügt leider nicht, der Shutdown soll "pausiert" und später fortgesetzt werden.

Tyrael Y. 3. Mär 2009 07:10

Re: WndProc in Komponente
 
WndProc kann nur in einem "Fenster" benutzt werden.
Dieses Fenster muss keine sichtbare Form sein.
Es genügt wenn du in deiner Komponente ein nicht sichtbares Fenster erzeugst.

Ja es wird definitiv Probleme mit einem Service und Window Messages unter Vista geben.
In Vista erreichen deine Messages den Service nicht, da es in einem eigenem Desktop läuft.
Hier wäre eine andere Art der Kommunikation von nöten. Ich selber bevorzuge TCP, da diese Technik definitiv nicht mal eben verschwinden wird.

Edit: Für dein Problem müsstest du in einer Applikation, dass ein "Fenster" enthält die entsprechenden Messages abfangen und über deinen bevorzugten Kommunikationskanal an den Service eine Nachricht schicken.

Angel4585 3. Mär 2009 11:51

Re: WndProc in Komponente
 
Was heisst du verwenedt TCP? Ich möchte ja die Systemnachricht die den Shutdown auslöst abfangen.
Wie unterscheide ich überhaupt ob Herunterfahren oder Neustart gewählt wurde?

Tyrael Y. 3. Mär 2009 12:14

Re: WndProc in Komponente
 
Unter Vista wirst du in deinem Service die Message für das Herunterfahren und "Neu Starten" nicht abfangen können, denke ich. Es kann natürlich sein, daß Systemnachrichten auf alle Desktops geschickt werden,
da ja auch der Service beendet werden muss. Ich weiss nicht ob es auch für die Service unter Vista noch so läuft.

Das hab ich noch nicht geprüft.

Ich weiss nur das man von einer Applikation zu einem Service keine Window-Messages unter Vista schicken kann, wegen den getrennten Desktops.

Sollten Systemnachrichten auch in diesem Service-Desktop verfügbar sein, musst du in deinem Service nur ein nicht sichtbares Fenster erzeugen und kannst eine WndProc benutzen.

Sollten diese Window-Messages nicht im Service-Desktop verfügbar sein, musst du eine Appliaktion haben die im User Desktop erstellt wird, dort die Window-Message abfängt und zB. über TCP an den Service eine Nachricht schickt á la "Hab Nachricht herunterfahren erhalten".

Angel4585 4. Mär 2009 08:41

Re: WndProc in Komponente
 
Das ist ne gute Idee, ich habe in nem anderen Thread folgenden Code gefunden welcher angeblich funktionieren soll, jedoch kommen keine Messages an, was ist falsch daran?
Im WndProc würde ich dann die Messages per TCP zum Dienst schicken.

Delphi-Quellcode:
program MyMessageCatcher;


uses
  Windows, SysUtils, Controls, Messages, ULogger, Classes, Forms;

type
  TWndThread = class(TThread)
  private
    FWndHandle : HWND;
    FCanEnd: Boolean;
  protected
    procedure Execute; override;
    procedure WndProc(var Msg: TMessage); virtual;
  public
    constructor Create(CreateSuspended: boolean);
    destructor Destroy; override;
    property CanEnd : Boolean read FCanEnd write FCanEnd;
  end;

constructor TWndThread.Create(CreateSuspended: boolean);
begin
  inherited Create(CreateSuspended);
try
  FCanEnd:=false;
  FWndHandle := Classes.AllocateHWnd(WndProc);
  snlogger.Log(inttostr(FWndHandle));
except on e:exception do snlogger.log('Create:'+e.message);end;
end;

destructor TWndThread.Destroy;
begin
try
  Classes.DeallocateHWnd(FWndHandle);
except on e:exception do snlogger.log('Destroy:'+e.message);end;
  inherited;
end;
 
procedure TWndThread.Execute;
var
  Msg: TMsg;
begin
try
  while GetMessage(Msg, 0, 0, 0) do
    begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
    end;
except on e:exception do snlogger.log('Execute:'+e.message);end;
end;

procedure TWndThread.WndProc(var Msg: TMessage);
begin
try
snlogger.Log(inttostr(Msg.Msg));

if Msg.Msg in [WM_QUERYENDSESSION,WM_ENDSESSION]then
  FCanEnd:=true;
except on e:exception do snlogger.log('WndProc:'+e.message);end;
end;



var FThread : TWndThread;
begin
  { TODO -oUser -cConsole Main : Hier Code einfügen }
try
FThread:=TWndThread.Create(false);
while not FThread.CanEnd do
  begin
  sleep(1);
  application.ProcessMessages;
  end;
except on e:exception do snlogger.log('main:'+e.message);end;

end.

Tyrael Y. 4. Mär 2009 09:09

Re: WndProc in Komponente
 
Hallo,

dieser Code setzt vorraus, daß du bereits ein Fenster hast. ;)
Du wirst nicht drumherum kommen, in deinem Fall, ein nicht sichtbares Fenster zu erzeugen.

Edit: Window-Message(WM_BLA)...ohne Fenster keine Message

Angel4585 27. Mär 2009 12:11

Re: WndProc in Komponente
 
Moin!

Das Problem mit einem sichtbaren Fenster ist: Das Programm was die Messages abfangen soll wird von einem Dienst heraus aufgerufen.(<= unschön?)
Nichtsdestotrotz habe ich jetz ein Programm mit Formular welches auch Messages empfängt, mitm Dienst gestartet.
Allerdings werden die Messages die ich brauche nicht abgefangen wie mir scheint(WM_QUERYENDSESSION und WM_ENDSESSION).

So soll da Ganze vorgehen: Dienst ruft "MessageCatcher" auf. Dieser soll Nachrichten abfangen um z.B. das herunterfahren des Rechners zu unterbrechen und später neu anzustoßen.

Bei den abgefangenen Messages sehe ich das in LParam was drinsteht, wie kann ich das dort auswerten?
Evtl hilft mir das weiter?


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:02 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