In Library Messages empfangen [gelöst]

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

In Library Messages empfangen [gelöst]

Beitrag von RSE »

Kontext: eine Library unter Windows (DLL), Plattformunabhängigkeit ist in diesem Fall nicht von Bedeutung

Wenn ich mich nicht irre, muss eine Klasse, die (funktionierende) Message-Methoden haben will, auch ein Window-Handle haben, also Nachfahre von TWinControl sein. Nach http://bugs.freepascal.org/view.php?id=7182 scheint aber genau das in Librarys nicht verwendbar. Nun frage ich mich, ob es nicht doch einen Weg gibt, dass man in einer Librarys an Windows-Messages herankommen kann. Bevor ich drauf gekommen bin, dass man Messages mit Message-Methoden empfangen kann, hatte ich glaube mal was von Hooks gelesen. Wenn ich mich recht erinnere, kann ich damit eine Prozedur angeben, in der ich jede Message überprüfen kann, bevor sie an das zum Handle gehörige window ausgeliefert wird. Dazu müsste ich natürlich auch erstmal ein window-Handle haben. Wie komme ich in einer Library an ein Window-Handle? Welche Ideen habt ihr noch? Welche ist die erfolgversprechendste Spur, der ich mich widmen sollte?
Zuletzt geändert von RSE am Mo 7. Dez 2009, 22:00, insgesamt 2-mal geändert.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: In Library Windows-Messages empfangen

Beitrag von mschnell »

AFAIK, kann man zu diesem Zweck "hidden Windows" erzeugen, die niemals sichtbar sind aber Messages empfangen können. Vermutlich tut man das am besten direkt über die entsprechende Windows API und nicht über die LCL.

Ich würde diese Art Kommunikations-Funktionen auf jeden Fall in eine spezielle Unit auslagern, da sie nicht auf Linux portierbar sind.

Möglicherweise ist so etwas aber auch in den Funktionen für Thread-Kommunikation bereits enthalten.

-Michael

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Windows-Messages empfangen

Beitrag von RSE »

Wie gesagt spielt Plattformunabhängigkeit dabei keine Rolle, weil ich in dieser Library eine DirectShow-Anbindung realisieren möchte. DirectShow ist das Multimediaframework von Windows. Die ganze Library soll also nur für Windows sein, allerdings soll das Library-Interface plattformunabhängig bleiben, damit ich später auch Anbindungen für GStreamer (für Linux) und Quicktime (MacOS) bauen kann.

Ich werde mich jetzt mal damit beschäftigen und melde mich wieder, wenn ich die nächsten Problemchen, die schon in Sicht sind, formulieren kann ;-)

Gibt es auf anderen Betriebssystemen eigentlich auch Window-Handles wie in Windows? Gibt es auch Messages? Gibt es eine Seite, auf der man sich belesen kann, wo Plattformabhänigkeit beginnt (bzgl. Handles und Messages und sowas, natürlich keine API-Aufrufe, das ist klar)?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: In Library Windows-Messages empfangen

Beitrag von mschnell »

Bei Linux ist das Thema komplexer, weil das System, in dem deine Anwendung läuft ja nicht nur aus Linux (dem Kernel) besteht, sondern Du vermutlich ja auch ein Darstellungs-System (X), ein Windowing-System (KDE, Gnome) und eine Widget-System (GTK) verwendest, die alle eigene Interfaces haben. Mindestens der Kernel und KDE stellen Messaging zur Verfügung. Beim Kernel z.B. "Signals", "System V Messages" und "Pipes", oft wird aber auch TCP/IP Rechner-intern verwendet, was (im Gegensatz zu Windows-internem TCP/IP) sehr performant ist. Bei KDE/GNOME und GTK etc. kenne ich mich nicht aus.

-Michael

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Windows-Messages empfangen

Beitrag von RSE »

WOW Also so ´ne Art Schichtenarchitektur, unterste Schicht ist der Kernel, dann X, dann ein Windowing System (Gnome oder KDE) und dann das Widget-Set (GTK, GTK2, QT). MacOS ist ja soweit ich weiß auch ein Linux-Derivat, so dass es dann genau die gleiche Architektur hat, nur als Widgetset dann Carbon oder Cocoa.

Nun will ja Lazarus genau davon abstrahieren, aber genau diese Funktionen sind wahrscheinlich eben nicht kompatibel mit den Bibliotheken, wenn ich das richtig sehe. Woran erkenne ich denn, wenn ich auf eine Plattformabhängige Eigenschaft zugreife? Ist THandle schon plattformabhängig? Das nächste Problem wird sein, ein Videofenster "einzufangen" und in meine Form zu integrieren. Dazu würde ich am liebsten irgendwie in der Biliothek das Fenster so an das Interface übergeben, dass es plattformunabhängig von der GUI in Empfang genommen werden kann. Sicherlich keine allzu einfache Aufgabe, vor allem wenn man nicht weiß, welche (Windowing-)Funktionen denn nun in Librarys sicher und plattformübergreifend verwendbar sind.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von RSE »

Also ich hab jetzt ein bissl gesucht und gefunden, dass man mit dem WinAPI-Aufruf CreateWindow (http://msdn.microsoft.com/en-us/library ... 85%29.aspx) ein Fenster erstellen kann. In meinem Fall bietet sich wohl Static oder Message an (http://msdn.microsoft.com/en-us/library ... spx#system). Wie finde ich die verwendete Windows-Version heraus, um zwischen Static und Message zu entscheiden? Mit der Einbindung der Unit Windows kann man CreateWindow verwenden, aber ich weiß nicht so recht, was ich da übergeben soll...

Nach weiterer Suche bin ich auf AllocateHWND gestoßen, dass es in Delphi genau für meinen Zweck gibt. Leider ist es in Lazarus offenbar nicht implementiert.

Wie komme ich an so ein Fenster, um Messages empfangen zu können?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von RSE »

Ich werd mir wohl das Handle vom MainWindow übergeben lassen und einen Hook setzen. Dann kann ich DirectShow die Messages an das MainWindow schicken lassen und sie mit dem Hook abfangen. Das ist zwar echt keine schöne Lösung, aber bei der weiß ich, wie ich es zu implementieren hab. Für Hilfe bei der Erzeugung eines Windows direkt in der Library bin ich natürlich immer dankbar und werde es dann umbauen, wenn mir die Umsetzung gelingt.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von mschnell »

MacOS basiert auf BSD und das ist wie Linux ein Unix-Derivat.

X ist eine Applikation, die neben den anderen Applikationen läuft und Grafik-Darstellungs-Aufträge von ihnen erhält. Dabei werden keine Fenster verwaltet. X wird über TCP/IP angesprochen und muss nicht auf demselben Rechner laufen wie die Anwenderprogramme. Es gibt auch X-Server-Programme, die auf Windows-Rechnern laufen.

Das Windowing -System ist ein permanent laufendes Programm und organisiert die die Window-Darstellung für die Anwender-Programme.

Das Widget-System ist (wenn ich das richtig sehe) eine Library, also Unterprogramm-Sammlung.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von mschnell »

RSE hat geschrieben:Nach weiterer Suche bin ich auf AllocateHWND gestoßen, dass es in Delphi genau für meinen Zweck gibt. Leider ist es in Lazarus offenbar nicht implementiert.

Wie komme ich an so ein Fenster, um Messages empfangen zu können?
Für private Zwecke kannst Du den Code für AllocateHWND aus der Delphi-VCL klauen. Das sind doch vermutlich nur ein paar Zeilen.

-Michael

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von RSE »

mschnell hat geschrieben:Für private Zwecke kannst Du den Code für AllocateHWND aus der Delphi-VCL klauen.
Hm, so wie es ist klauen wohl eher nich, aber wenn ich es verstehe, kann ich ja ähnliches selbst proggen, allerdings hab ich die VCL-Sources nicht verfügbar. Falls du sie verfügbar hast, wäre ich dir äußerst verbunden, wenn du sie mir zukommen lassen könntest. Falls es hier öffentlich im Forum zu rechtlichen Probs führe könnte, dann vielleicht per PM, aber es geht ja nicht um ein Klauen der Implementation, sondern um die Diskussion eines Beispiels. Sorry, aber ich komm da ohne Hilfe echt nicht weiter. Nach Message und Window lässt sich echt besch... googeln!

Ich habe jetzt aber noch ein paar Infos, womit ich mir folgendes zusammengebastelt habe, was zumindest der Compiler erst einmal nicht anmeckert (Ich hab keine Ahnung, ob die Werte, die ich da übergebe tatsächlich so übergeben werden sollen):

Code: Alles auswählen

var
  HWindow: HWND;
begin
  HWindow := CreateWindow(PChar('Static'),PChar(''),WS_DISABLED,0,0,0,0,0,0,HINSTANCE,nil);
In der Doku im MSDN steht "Before returning, CreateWindow sends a WM_CREATE message to the window procedure.", allerdings wird mit CreateWindow gar keine solche Procedure übergeben! Wie soll ich diese Message empfangen? Wie gebe ich eine WindowProcedure an? Offenbar steckt das alles irgendwie in der Klasse "Static" drin, die ich irgendwie vorher wohl noch ableiten muss oder so, um meinen eigenen Message-Handler zu schreiben...
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von mse »

RSE hat geschrieben: In der Doku im MSDN steht "Before returning, CreateWindow sends a WM_CREATE message to the window procedure.", allerdings wird mit CreateWindow gar keine solche Procedure übergeben! Wie soll ich diese Message empfangen? Wie gebe ich eine WindowProcedure an? Offenbar steckt das alles irgendwie in der Klasse "Static" drin, die ich irgendwie vorher wohl noch ableiten muss oder so, um meinen eigenen Message-Handler zu schreiben...
WindowProcedure wird in RegisterClass() als lpfnWndProc in der WNDCLASS Struktur übergeben oder mit SetWindowLong() mit GWL_WNDPROC gesetzt. MSEgui Beispiel: lib/common/kernel/i386-win32/mseguiintf.pas gui_init() Funktion.
http://mseide-msegui.svn.sourceforge.ne ... 386-win32/

Martin

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von mschnell »

RSE hat geschrieben:Nach weiterer Suche bin ich auf AllocateHWND gestoßen, dass es in Delphi genau für meinen Zweck gibt. Leider ist es in Lazarus offenbar nicht implementiert.
In meinen (nicht ganz aktuellen) LCL- und FPC- Sourcen gibt es durchaus eine (oder mehrere) Implementierung von AllocateHWND. Such 'mal nach AllocateHWND in allen *.pas, *.pp und *.inc - Dateien !

-Michael

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von RSE »

Sorry, hab die letzten Tage leider nix machen können, uns ist das Aquarium kaputt gegangen. Zum Glück nur gerissen und nicht geplatzt, so haben wir das Wasser noch ablassen können. Wir hatten sogar noch ein leeres kleines 80l-Becken für die Fische rumstehen. Ich hoffe ihr hattet einen erfreulicheren Nikolaustag...

Ich hab mir jetzt was zusammengebastelt, das allem Anschein nach funktioniert. Die Sourcen von mse sind mir allerdings ein bissl zu schwierig gewesen, ich hab mich größtenteils an http://www.delphipraxis.net/post1107527.html orientiert. Hier das Ergebnis:

Code: Alles auswählen

program project1;
...
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Windows;
...
var
  MyHandle: HWND;
  MyClass: TWndClass;
 
function MyWndProc(Handle:HWND; MyMsg:UINT; _MyWParam:WPARAM; MyLParam:LPARAM): LRESULT; stdcall;
begin
  case MyMsg of
    WM_GETMINMAXINFO: Result := 0; // maximized Size
    WM_NCCREATE: Result := 1;
    WM_CREATE: Result := 0;
    WM_NCCALCSIZE: Result := 0; // Resize
    WM_NCDESTROY: Result := 0;
    WM_DESTROY: Result := 0;
  else // die behandelten Messages treten alle auf, weitere nicht
    Result := 0;
  end;
end;
 
begin
  MyClass.lpfnWndProc := @MyWndProc;
  MyClass.lpszClassName := PChar('TMyClass');
  MyClass.hInstance := HInstance;
  if RegisterClass(MyClass) = 0 then
    Exit;
  try
    MyHandle := CreateWindow(PChar('TMyClass'),PChar(''),WS_DISABLED,0,0,0,0,0,0,HInstance,nil);
    if MyHandle = 0 then
      Exit;
    DestroyWindow(MyHandle);
  finally
    UnregisterClass(PChar('TMyClass'),HInstance);
  end;
end.
Falls es noch Verbesserungsvorschläge gibt, dann immer her damit! :-D
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von mse »


RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: In Library Messages empfangen und Windows zurückgeben

Beitrag von RSE »

Hm, das ist ja fast genau so wie bei mir implementiert, scheint wohl nicht ganz falsch zu sein :-p Danke!

Ich habe meine Implementierung entsprechend angepasst:

Code: Alles auswählen

program project1;
...
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Windows;
...
var
  MyHandle: HWND;
  MyClass: TWndClass;
 
function MyWndProc(Handle:HWND; MyMsg:UINT; _MyWParam:WPARAM; MyLParam:LPARAM): LRESULT; stdcall;
//var
//  MyInstance: TMyInstance;
begin
//  MyInstance := TTMyInstance(GetWindowLongPtr(HWindow,GWL_USERDATA)); // Ist für die Integration in Klassen sehr hilfreich <<<<< hier
  case MyMsg of
    WM_NCCREATE: Result := 1;
    WM_NCCALCSIZE: Result := 0; // Resize
    WM_CREATE: Result := 0;
    WM_SIZE: Result := 0; // <<<<< hier
    WM_MOVE: Result := 0; // <<<<< hier
    WM_GETMINMAXINFO: Result := 0; // maximized Size <<<<< tritt jetzt nicht mehr auf, dafür alle anderen in dieser Reihenfolge
    WM_DESTROY: Result := 0;
    WM_NCDESTROY: Result := 0;
  else // weitere Messages treten nicht auf
    Result := 0;
  end;
end;
 
begin
  Pointer(MyClass.lpfnWndProc) := @MyWndProc; // <<<<< hier
  MyClass.lpszClassName := PChar('TMyClass');
  MyClass.hInstance := HInstance;
  if RegisterClass(MyClass) = 0 then
    Exit;
  try
    MyHandle := CreateWindowEx(WS_EX_TOOLWINDOW,PChar('TMyClass'),PChar(''),WS_POPUP,0,0,0,0,0,0,HInstance,nil); // <<<<< hier
    if MyHandle = 0 then
      Exit;
//  SetWindowLongPtr(MsgWinHandle,GWL_USERDATA,PtrInt(Self)); // Ist für die Integration in Klassen sehr hilfreich <<<<< hier
    DestroyWindow(MyHandle);
  finally
    UnregisterClass(PChar('TMyClass'),HInstance);
  end;
end.
Ich kenne zwar nicht den genauen Grund, warum WS_EX_TOOLWINDOW und WS_POPUP verwendet werden soll, aber die Lazarus-Entwickler wissen schon, was sie tun.

Vielen Dank an alle Helfer!
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Antworten