Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   DLL Messagequeue (https://www.delphipraxis.net/159205-dll-messagequeue.html)

schwa226 18. Mär 2011 06:40

DLL Messagequeue
 
Guten Morgen!

Ich hänge mal wieder mit einer umsetzung von C++ nach Delphi.
Und zwar habe ich nach diesem Demos:
http://www.infinityusb.com/default.a...&DownloadID=43

die INFSMART.PAS erzeugt.

In der Demo werden diese Funktionen in einer Anwendnung mit einer Form benutzt.
Ich möchte es aber in einer DLL benutzen die keine Form hat.

Das Problem ist, dass die DLL nun bei dem Aufruf von
Delphi-Quellcode:
TINFSMART_OpenDeviceFromNum = function (dwDevice: DWORD;
                                    hDevice: PDWORD;
                                    lpDeviceString: PAnsiChar): SDK_STATUS; stdcall;
stehen bleigt und nicht zurückkommt.


Die Funktion vorher
Delphi-Quellcode:
TINFSMART_GetNumDevices = function (lpdwNumDevices: PDWORD): SDK_STATUS; stdcall;
geht noch ohne Probleme.

Die Demo läuft die ganze Zeit in dieser Funktion und arbeitet die Messagequeue ab:
Code:
   // Main message loop:
   while (GetMessage(&msg, NULL, 0, 0))
   {
      if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
   }
Wie kann ich das am einfachsten in einer Delphi DLL verwirklichen?

DeddyH 18. Mär 2011 08:54

AW: DLL Messagequeue
 
Du könntest ein MessageOnly-Window samt zugehöriger WndMethod erzeugen: Delphi-Referenz durchsuchenAllocateHwnd

himitsu 18. Mär 2011 09:02

AW: DLL Messagequeue
 
Aufpassen, AllocateHwnd erstellt ein Wincontrol, welches in der VCL läuft.

Aber wenn die DLL keinen Messagebehandlung für die VCL bereitstellt, dann hängt es auch da.
Eventuell läuft es aver über die VCL der EXE, was allerdings auch Problemchen bereiten könnte.

CreateWindow/CreateWindowEx zum Erstellen eines MessageWindows und eine MessageLoop in einem eigenem Thread könnte da helfen. (Erstellen der Windows und die MessageLoop müssen immer selben Thread ablaufen)


PS: Eine DLL/EXE haben keine MessageQueue ... diese ist immer an einen Thread gebunden und wer einen Thread erstellt ist egal.
Die Messages der Windows werden immer an die Queue geschickt, in welchem Thread das Window erstellt wurde.

DeddyH 18. Mär 2011 09:14

AW: DLL Messagequeue
 
Zitat:

Zitat von himitsu (Beitrag 1089415)
Aufpassen, AllocateHwnd erstellt ein Wincontrol, welches in der VCL läuft.

Das verstehe ich aber anders.
Zitat:

Erstellt ein Fenster, das eine bestimmte Fensterprozedur implementiert.

Mit AllocateHWnd können Sie ein Fenster erstellen, das keinem fensterorientierten Steuerelement zugeordnet ist. Die Funktion wird normalerweise zur Erstellung nichtvisueller Fenster verwendet, die zwar auf Botschaften reagieren, aber nicht in der Benutzeroberfläche angezeigt werden. Sie wird beispielsweise von der Komponente TTimer aufgerufen, um ein Fenster für die Timer-Ereignisse von Windows zu erstellen.

Der Parameter Method gibt die Fensterprozedur an, die vom neuen Fenster für die Reaktion auf Botschaften verwendet wird.

AllocateHWnd gibt das Handle des neuen Fensters zurück.

Anmerkung: Geben Sie die mit AllocateHWnd erstellten Fenster mit der Prozedur DeallocateHWnd frei.

schwa226 18. Mär 2011 09:29

AW: DLL Messagequeue
 
Danke einmal für die Antworten!

Ich habe mit dem Hersteller Kontakt aufgenommen und dieser hat mir gesagt, dass es ohne Probleme gehen sollte. Da er aber keine Delphi Implementierung zur Verfügung stellt redet er sich natürlich darauf aus...

Inzwischen ist mir eingefallen, dass ich schon einmal mit einer DLL und USB-HID Device gekämpft habe. Auch hier war das Problem, dass die DLL stehen geblieben ist. In einer Anwendung mit Form ging es ohne Probleme. Dazu muss ich mir das aber noch ansehen was ich da gemacht habe um dieses Problem zu umgehen.

noch schnell gesucht:
http://www.delphipraxis.net/1015009-post23.html
(war aber das Problem, dass es bei WaitFor stehen geblieben ist)

Auch werde ich die INFSMART.PAS einmal mit einer Anwendung mit Form verwenden. Da bin ich mir eigentlich sicher dass es funktioniert.

himitsu 18. Mär 2011 09:34

AW: DLL Messagequeue
 
Egal in welchem Thread man AllocateHWnd aufruft, die Messages werden immer an den VCL-Thread gesendet.

Wenn man also eine eigene MessageLoop nutzen will, sollte man da aufpassen.

schwa226 18. Mär 2011 11:36

AW: DLL Messagequeue
 
So,

wie ich mir gedacht habe läuft es mit einer VCL Application ohne Probleme.
Ich kann das Device öffnen und wieder schließen.

In der DLL bleibt es beim Öffnen stehen.
Auch ein Einbinden der D6DLLSynchronizer.pas hat nichts gebracht. Diese würde ja ein AllocateHWnd durchführen.

Jetzt stellt sich mir die Frage wie ich das machen kann damit es in der DLL auch funktioniert!?

Das ganze in einen eignenen Thread auszulagern möchte ich eigentlich umgehen.

Edit:
Jetzt habe ich einfach das einmal Probiert:
Delphi-Quellcode:
Type
  TTest = class(TThread)
    private
    public
      constructor Create();
    protected
      procedure Execute; override;
    end;

constructor TTest.Create();
begin
  inherited create(True); // CreateSuspended = true

  FreeOnTerminate := True;
end;

procedure TTest.Execute;
var
  msg : Tmsg;
begin
  while not Terminated do
  begin
    Sleep(1);
  end;
end;
In meiner DLL rufe ich dann auf:
Delphi-Quellcode:
            test := TTest.Create;
            test.Start;
Nun wird der Thread erzeugt, aber trotz Start kommt er nicht in die Execute?
Ein Breakpoint in der Execute bleibt unangetastet. Die DLL arbeitet aber step für step weiter.

Wenn schon dieser Thread nicht ausgeführt wird kann das auch der Grund sein warum es mit der Funktion auch nicht geht.

schwa226 18. Mär 2011 14:15

AW: DLL Messagequeue
 
Habe es nun doch noch geschafft!

Die Funktion darf nicht im öffnen der DLL aufgerfufen werden.
Wenn ich sie über eine exported Funktion aufrufe geht es ohne Probleme.

Nun habe ich aber noch eine Frage zwecks C++ -> Delphi:
Code:
INFSMART_SDK   SDK_STATUS      _stdcall INFSMART_Phoenix_Enable(HANDLE hDevice, unsigned int baud, unsigned int * ActualBaud, unsigned char stopbit, unsigned char parity, unsigned char databits, unsigned int dwFrq, unsigned int PhRunningFrq, bool updateonly);
Delphi:
Delphi-Quellcode:
TINFSMART_Phoenix_Enable = function (hDevice: THandle;
                                 baud: DWORD;
                                 ActualBaud: PDWORD;
                                 stopbit: Byte;
                                 parity: Byte;
                                 databits: Byte;
                                 dwFrq: DWORD;
                                 PhRunningFrq: DWORD;
                                 updateonly: Bool): SDK_STATUS; stdcall;
Sollte so passen, oder?


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