![]() |
DLL Init, Timer läuft nicht an
Hi,
ich habe eine DLL gemacht, die beim Init eine Form erzeugt und einen Timer startet:
Delphi-Quellcode:
Wenn die DLL nun von eine Test-VCL Form von Delphi geladen wird und das Init aufgerufen wird, wird das Timer Event von StartUpDelay ausgelöst.
function InitDLL(Callback : TCallback):Boolean; stdcall;
begin try //plugin gets loaded, create Form if Not Assigned(frMain) then frMain := TfrMain.Create(NIL); frMain.AddLog('plugin got init'); //start startupdelay frMain.StartStartUpDelay(StartDelay); finally Result := Assigned(frMain); end; end; end; procedure TfrMain.StartStartUpDelay(Interval:Integer); begin //start startup delay StartUpDelay.Interval := Interval; StartUpDelay.Enabled := True; end; Wenn die DLL aber von einer C-Console-App (VS2008) geladen wird, wird das Timer Event nicht ausgelöst!? Erst wenn ich die Form anzeige wird das Event ausgelöst:
Delphi-Quellcode:
Sobald Showmodal aufgerufen wird spingt der Code in die StartUpDelay Timer Routine.
procedure ShowForm();
begin if Assigned(frMain) then begin frMain.ShowModal; end; end; Woran kann das liegen? |
Re: DLL Init, Timer läuft nicht an
Darum nutzt man keine VCL in einer DLL.
- der Timer wird über die VCL gesteuert - in deiner DLL hast du keine Nachrichtenbehandlung (Windows-Messages) eingebaut - die Nachrichtenschleife der EXE behandelt alle Nachichten und leitet sie an die DLL weiter - eine C-EXE hat zwar (vermutlich) eine Nachrichtenschleife, aber diese behandelt garantiert keine Delphi-Ereignisse Wenn unbedingt VCL in DLL, - dann erstelle und behandle diese in einem eigenem Thread und arbeite in diesem Thread die Nachrichten ab - und es darf keine Interation zwischen den beiden VCLs (EXE und DLL) geben, denn die VCL ist nicht threadsicher |
Re: DLL Init, Timer läuft nicht an
Zitat:
- Es gibt in diesem Fall absolut nichts verwerfliches daran in diesem Fall die VCL in der DLL zu verwenden. - Das der Timer über die VCL gesteuert wird ist nur bedingt richtig. Der Timer ist wohl Teil der VCL (je nach dem wie man VCL definiert) aber letztendlich wird er über das Windows-Nachrichtensystem gesteuert. - Das die Nachrichtenschleife der Exe alle Nachrichten behandelt und diese an die DLL weiter leitet ist nur bedingt richtig. Eine Nachrichtenschleife behandelt alle Nachrichten des Threads in der die Schleife läuft. Da der Timer im Kontext des Hauptthreads der Exe erstellt wurde, werden die Nachrichten aller Fenster (und nichts anderes empfängt die Timernachrichten in der Timerklasse) dieses Threads, inklusive derer aus der DLL verarbeitet. Ebenso würde aber auch eine Nachrichtenschleife innerhalb der DLL die Nachrichten für die Fenster in der EXE verarbeiten sofern diese im gleichen Threadkontext laufen. - Eine Nachrichtenschleife in einem C-Programm verarbeitet garantiert auch die Nachrichten welche für Fenster sind die aus Programmen/Programmteilen anderer programmiersprachlicher Herkunft sind. Die Begründung warum es nicht funktioniert liegt hierin: Zitat:
|
Re: DLL Init, Timer läuft nicht an
Es gibt aber auch eine Menge delphieigener Messages, welche direkt in Delphis Nachrichtenschleife behandelt werden
und Solche werden nicht von einer "fremden" Nachrichtenschleife behandelt. |
Re: DLL Init, Timer läuft nicht an
Hast du dich mal mit Nachrichtenschleifen beschäftigt? Zumindest alle Punkt die ich von dir zitiert habe trafen in diesem konkreten Beispiel nicht zu. Und dem Fragesteller ging es nicht darum was allgemein irgendwann mal sein kann sondern er wollte wissen warum im konkreten Fall der Timer seinen Dienst nicht verrichtet. Und da waren die von dir genannten Punkte schlichtweg falsch.
Aber auch die letzte Aussage würde ich so nicht stehen lassen. Ich bin der Meinung (bin mir hier aber nicht zu 100% sicher) das nicht die Nachrichtenschleife spezielle Messages verarbeitet. Vielmehr holt die Nachrichtenschleife nur die Nachrichten aus der Nachrichtenwarteschlange ab und leitet diese durch den Aufruf von Windowsfunktionen an die entsprechende registrierten Nachrichtenfunktionen weiter. So sieht übrigens eine Nachrichtenschleife in C aus:
Code:
In Delphi sieht sie übrigens nicht groß anders aus. Es werden die gleichen Funktionen aufgerufen. Rein der Syntax der Programmiersprache unterscheidet sich.
while (GetMessage(&Message, NULL, 0,0))
{ TranslateMessage(&Message); DispatchMessage(&Message); } |
Re: DLL Init, Timer läuft nicht an
Danke euch beiden erst einmal!
Gibt es zu dem Thread/Message abarbeiten ein Beispiel. Werde warscheinlich im Thread mit GetMessage ein Polling machen müssen und die WM_TIMER dann per PostMessage an mein HWND weiterleiten!? |
Re: DLL Init, Timer läuft nicht an
Zitat:
Delphi-Quellcode:
var
Msg: TMsg; begin while ProcessMessage(Msg) do {loop}; function TApplication.ProcessMessage(var Msg: TMsg): Boolean; var Handled: Boolean; Unicode: Boolean; MsgExists: Boolean; begin Result := False; MsgExists := PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE); if MsgExists or PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then begin Unicode := (Msg.hwnd = 0) or IsWindowUnicode(Msg.hwnd); if not MsgExists then begin if Unicode then MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE) else MsgExists := PeekMessageA(Msg, 0, 0, 0, PM_REMOVE); end; if MsgExists then begin Result := True; if Msg.Message <> WM_QUIT then begin Handled := False; if Assigned(FOnMessage) then FOnMessage(Msg, Handled); if not IsPreProcessMessage(Msg) and not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then begin TranslateMessage(Msg); if Unicode then DispatchMessageW(Msg) else DispatchMessageA(Msg); end; end else begin {$IF DEFINED(CLR)} if Assigned(FOnShutDown) then FOnShutDown(self); DoneApplication; {$IFEND} FTerminate := True; end; end; end; end; |
Re: DLL Init, Timer läuft nicht an
Sorry, aber auch da sehe ich keine wirkliche Sonderbehandlung. Es wird die Message lediglich für das Application-Object etc. bereit gestellt. Aber eine besondere Behandlung einzelner Messages sehe ich hier nicht. Aber das ist auch egal. Mir ging es nur darum einige Aussagen richtig zu stellen damit der Fragestellende nicht den Eindruck bekommt wirklich alles falsch gemacht zu haben wenn im konkreten Fall der einzige "Fehler" ist keine Nachrichtenschleife zu haben.
|
Re: DLL Init, Timer läuft nicht an
Für den Timer selber könnten diese Befehle entscheidend sein ... man weiß ja nicht was da intern noch alles passiert.
Delphi-Quellcode:
Und dann wird der Timer nicht einzeln verwaltet.
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsPreProcessMessage(Msg) and ... and not Handled Ein Timer ohne Form/Owner muß nicht das Selbe sein, wie Einer mit Form/Owner ... hier kann es auch sein, daß schon bei dessen Erstellung etwas schief läuft, also z.B. wärend die Form erstellt/verwaltet wird. Der Code vom TTimer selber ist noch relativ primitiv und dürfte so vermutlich auch in der C-Nachrichtenschleife behandelt werden, aber das TComponent hinter dem TTimer verbirgt 'ne Menge unberechenbaren VCL-Code. Wie gesagt, der einfachste und sicherste Weg die VCL innerhalb einer "autonomen" DLL zu verwalten, wäre diese VCL in einem separaten Thread und mit eigener Nachrichtenschleife laufen zu lassen. |
Re: DLL Init, Timer läuft nicht an
Zitat:
Im Execute vom Thread dann wie am besten die Nachrichten abarbeiten? Tut leid, aber ich steh momentan voll auf dem Schlauch... :roll: Danke! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:31 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