FindWindow - Unterschied zu Delphi

Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

Hallo zusammen,

ich fange gerade erst mit Lazarus an und möchte damit einige Projekte für Linux (CentOS) und Windows (64Bit) realisieren.

Dazu habe ich erstmal ein kleineres Delphiprojekt nach Lazarus portiert. Es ist eine Anwendung, die über Postmessage von anderen Anwendungen auf dem selben Rechner gesteuert wird.

Um mit dem Programm zu kommunizieren habe ich unter Delphi folgenden Code verwendet, der dort einwandfrei funktioniert.

Code: Alles auswählen

hExisting := FindWindow('TfrmTest', nil);


Leider funktioniert FindWindow unter Lazarus wohl offenbar etwas anders als unter Delphi (D2010), denn ich bekomme auf diese Weise kein Windowhandle zurück.

Trotz einigem Suchen habe ich bisher dafür keine Lösung gefunden.

Kann es sein, dass Lazarus WinClassName überhaupt nicht besetzt?

Würde mich über Antworten oder Hinweise freuen.


Grüße,
Uwe

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: FindWindow - Unterschied zu Delphi

Beitrag von theo »

Uwe_9988 hat geschrieben:ich fange gerade erst mit Lazarus an und möchte damit einige Projekte für Linux (CentOS) und Windows (64Bit) realisieren.
Dazu habe ich erstmal ein kleineres Delphiprojekt nach Lazarus portiert.

...und musste gleich mit dem (Cross Platform) kompliziertesten beginnen.... ;-)

Wo hast du denn überhaupt ein Cross-Platform FindWindow-Funktion gefunden? Afaik ist das nur WinAPI.
Für Cross-Platform wäre es wahrsch. besser die Kommunikation mit SimpleIPC oder TCP/IP zu machen.

Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

Re: FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

theo hat geschrieben:...und musste gleich mit dem (Cross Platform) kompliziertesten beginnen.... ;-)


Dass ich gerade mit Lazarus anfange, heißt ja nicht, dass ich blutiger Anfänger in Sachen Programmierung bin. ;)

theo hat geschrieben:Wo hast du denn überhaupt ein Cross-Platform FindWindow-Funktion gefunden? Afaik ist das nur WinAPI.
Für Cross-Platform wäre es wahrsch. besser die Kommunikation mit SimpleIPC oder TCP/IP zu machen.


Crossplatform ist sicherlich eine interessante Sache aber zunächst geht es mir eher darum wenigstens mal ein kleines Delphiprojekt unter Lazarus zum Laufen zu bringen. Wie man es dann unter Linux funktionstüchtig bekommt, ist erst der nächste Schritt.

Bei uns geplante Programme werden auch selten auf mehreren Plattformen laufen müssen. Entweder Linux oder Windows.

Da FindWindow ja eine API-Funktion ist, hat es mich ja auch gewundert, dass mein Beispiel-Projekt gerade daran scheitert. Also lauffähiges Win32-Delphi-Projekt nach 64Bit-Windows-Lazarus-Projekt portieren ist im Moment gefragt. Da ich einer anderen Anwendung eine Message mit PostMessage schicken muss, benötige ich deren Handle. Deshalb der Ansatz mit FindWindow, der ja normalerweise wunderbar funktioniert.

Delphi (D2010) besetzt WinClassName offenbar mit dem Klassennamen des Mainform und Lazarus lässt es meiner Meinung nach leer. Ergo findet man mit FindWindow nichts.

Ist das ein schon bekanntes Problem oder wie bekommt man denn nun unter Lazarus ein Handle auf eine andere Anwendung, wenn man deren MainForm-Klassennamen kennt?


Grüße,
Uwe

Linkat
Lazarusforum e. V.
Beiträge: 530
Registriert: So 10. Sep 2006, 23:24
OS, Lazarus, FPC: Linux Mint 21.3; Lazarus 3.0 FPC 3.2.2; RaspiOS
CPU-Target: AMD 64, ARM 32
Wohnort: nr Stuttgart

Re: FindWindow - Unterschied zu Delphi

Beitrag von Linkat »

Hallo Uwe,
ich beschäftige mich gerade auch mit FindWindow siehe:
http://www.lazarusforum.de/viewtopic.php?f=55&t=4584
Ich habe festgestell, dass FindWindow in WinXP nicht immer so funktioniert, wie erwartet. Ob es nun an der WinAPI liegt, oder an der Anbindung durch Lazarus, kann ich nicht sagen.
Aber vielleicht bescheibst du einfach mal dein Problem ein bischen genauer.

Gruß, Linkat
Linux Mint 21; Lazarus 2.2.4 FPC 3.2.2; RaspiOS

Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

Re: FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

Hallo Linkat,

also ich habe FindWindow mit Delphi eigentlich fast in jeder Anwendung benutzt und nie ein Problem festgestellt.

Die beiden Parameter, die FindWindow akzeptiert sind der Klassenname des Fensters und der Titel = Caption des Fensters welches man sucht. Letzteres finde ich etwas ungeeignet um eine Anwendung zu suchen, deswegen rufe ich FindWindow normalerweise nur mit dem Klassennamen des Main/Subform auf.

Im einfachsten Fall prüfe ich damit ob die Anwendung schon gestartet ist oder nicht. Manche sagen, dass sei eine unsichere Methode, aber bisher konnte mir niemand sagen, was daran unsicher sein soll, wenn man seine Forms eindeutig benennt. :)

Das sieht dann etwa so aus:

Code: Alles auswählen

begin
  // Speicherlecks in der IDE anzeigen
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
  // Programm nur einmal starten
  hExisting := FindWindow(PWideChar(TfrmTemplate.ClassName),  nil); // Klassenname des Formulars (default wäre TForm1), Caption egal
  if hExisting > 0 then // Anwendung gefunden. Handle ist ungleich 0.
  begin
    Application.Terminate; // Anwendung läuft schon, also nicht nochmal starten.
  end
  else // Anwendung läuft noch nicht. Starten!
  begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TfrmTemplate, frmTemplate);
    Application.Run;
  end;
end.


Unter Delphi funktioniert das so. Mit Lazarus leider nicht (hExisting ist immer 0). Dabei scheint nicht FindWindow das Problem zu sein, sondern Lazarus, da offenbar die Exe nicht den entsprechenden Klassennamen enthält und somit FindWindow kein entsprechendes Ergebnis liefern kann.

Für genau dieses Problem (läuft die Anwendung schon?) kann man sich mit der Unit UNIQUEINSTANCE helfen, da man damit auch überprüfen kann ob eine Anwendung schon läuft (und das sogar plattformunabhängig).

Aber da ich, wie beschrieben, ja mit PostMessage eine Message an eine andere Anwendung schicken muss, benötige ich wirklich das Fensterhandle um weiterzukommen.

Dass es sicherlich auch andere Methoden gibt um Anwendungen miteinander kommunizieren zu lassen, ist klar aber weshalb ist FindWindow im Windowsteil von Lazarus definiert, wenn es nicht so funktioniert, wie in der Api beschrieben? Wenn es ein Bug ist, dann wäre mir schon geholfen, wenn das jemand bestätigen könnte. ;)


Grüße,
Uwe

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: FindWindow - Unterschied zu Delphi

Beitrag von Socke »

Wie kommst du denn auf die Idee, dass du TfrmTemplate.ClassName in einen PWideChar casten kannst? FreePascal unterstützt keine implizite Konvertierung von Short-/Ansistrings in PWideChar.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

Re: FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

Hallo Socke,

Gegenfrage: Wie kommst du darauf, dass der obige Source schon mal einen FP-Compiler gesehen hat? :mrgreen:

Das war natürlich ein Beispiel, das aus einem Delphiprojekt stammt. Dachte, das wäre spätestens bei:

Code: Alles auswählen

// Speicherlecks in der IDE anzeigen
ReportMemoryLeaksOnShutdown := DebugHook <> 0;

klar.

In Lazarus habe ich TfrmTemplate.Classname natürlich als PChar übergeben. Das Ergebnis war wie oben beschrieben. Auch eine Übergabe als Literal wurde natürlich getestet.

Problem nach wie vor ungelöst. :(


Gibt es noch etwas konstruktivere Lösungsvorschläge? ;)


Grüße,
Uwe

u-boot
Beiträge: 306
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: FindWindow - Unterschied zu Delphi

Beitrag von u-boot »

Ja ich glaub dieses findwindow sucht noch paar halbwegs erfahrene Pascal-Programmierer um verbessert zu werden... könntest du nich ? ....
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: FindWindow - Unterschied zu Delphi

Beitrag von Hitman »

FindWindow plattformunabhängig zu implementieren ist nahezu unmöglich. Das Konzept mit Window-Handle, Window-Class und Window-Title findest du in der Form eben nur unter Windows. Wenn du einen Check durchführen willst, ob deine Anwendung bereits läuft, schau mal im Wiki/CCR nach, dort ist eine Lösung, die IPC nutzt - das ist dann plattformunabhängig und klappt sogar komplett ohne GUI.

Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

Re: FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

Hallo zusammen,

danke für's Feedback.

Also ich habe mal ein wenig geforscht und es scheint so zu sein, dass jede Lazarusanwendung in WinClassName den vielsagenden Bezeichner "Window" verpasst bekommt. :mrgreen: Eben diesen WinClassName kann man mit FindWindow suchen.

Damit ist FindWindow um den sinnvollen Teil kastriert worden. Eine Laz-Anwendung ist somit über FindWindow nur noch an der Caption zu erkennen, was ja schon so einige Nachteile hat.

Ich habe mal versucht, den entsprechenden Teil in den Sourcen zu ändern, aber dabei ist mir Lazarus komplett um die Ohren geflogen. :shock: Ich installiere es mal eben neu, damit ich Euch sagen kann, wo das war. Irgendwas mit W32Forms oder so...dort ist die Konstante ClsName definiert (='Window').

@Hitman: Ist schon klar, dass es nicht so ohne weiteres möglich ist FindWindow plattformübergreifend hinzubekommen aber im Moment geht's eher darum, dass es erstmal unter Windows so funktioniert, wie in der API versprochen. ;) Aber unter Linux haben doch Fenster sicherlich auch so etwas wie ein Handle oder? Oder wie werden Fenster dort voneinander unterschieden? Gibt es keine ähnliche Funktion unter Linux? Habe leider gar keinen Plan, wie Linuxanwendungen miteinander "reden".

@all: FindWindow an sich funktioniert ordnungsgemäß, auch unter Lazarus aber wenn sich jede Laz-Anwendung mit der Klasse "Window" bei FindWindow zu erkennen gibt, ist's halt etwas dämlich. :) Eine Delphi-Exe lässt sich mit einer Laz-Exe und Findwindow problemlos über den Klassennamen des Mainform finden. Habe ich probiert.

Bisher habe ich mit Lazarus 0.9.28 experimentiert. Kann mir jemand sagen ob sich die Problematik in der aktuellen SVN-Version noch ebenso verhält oder hat sich da vielleicht schon etwas getan?


Grüße,
Uwe

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: FindWindow - Unterschied zu Delphi

Beitrag von Socke »

Uwe_9988 hat geschrieben:@Hitman: Ist schon klar, dass es nicht so ohne weiteres möglich ist FindWindow plattformübergreifend hinzubekommen aber im Moment geht's eher darum, dass es erstmal unter Windows so funktioniert, wie in der API versprochen. ;) Aber unter Linux haben doch Fenster sicherlich auch so etwas wie ein Handle oder? Oder wie werden Fenster dort voneinander unterschieden? Gibt es keine ähnliche Funktion unter Linux? Habe leider gar keinen Plan, wie Linuxanwendungen miteinander "reden".

Unter Linux gibt es verschiedene Möglichkeiten miteinander zu reden. Die Häufigsten sind TCP/IP oder Pipes. "Fenster" gibt es aber unter "Linux" gar keine. Dazu musst du dich an deine grafische Oberfläche (wahrscheinlich X11) und deinen Fenstermanager wenden. Welcher das ist, hängt von deinen persönlichen Vorlieben ab. Eventuell mag dir auch dein Widgetset weiterhelfen (aber eher unwahrscheinlich).

Uwe_9988 hat geschrieben:@all: FindWindow an sich funktioniert ordnungsgemäß, auch unter Lazarus aber wenn sich jede Laz-Anwendung mit der Klasse "Window" bei FindWindow zu erkennen gibt, ist's halt etwas dämlich. :) Eine Delphi-Exe lässt sich mit einer Laz-Exe und Findwindow problemlos über den Klassennamen des Mainform finden. Habe ich probiert.

Hast du nicht grundsätzlich das Problem, dass mehrere Instanzen deiner zu suchenden Anwendung (und damit des Fensters) existieren können?
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

Re: FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

Hallo Socke,

hmm, da habe ich wohl etwas falsch verstanden. :)

Ich dachte, dass man mit Lazarus grundsätzlich Anwendungen für ein fensterorientiertes Betriebssystem schreibt. Natürlich gibt es Konsolenanwendungen in jedem BS aber das Gros dürfte sich doch einer grafischen Oberfläche bedienen.

Ich würde eine Anwendung schon plattformunabhängig nennen, wenn sie jeweils unter Windows, Linux/KDE/Gnome und Mac innerhalb der grafischen Oberfläche läuft. Aber ist schon klar, dass Lazarus da vielleicht einen höheren Anspruch hat.

FindWindow bezieht sich doch eindeutig auf eine grafische Oberfläche. In einer WinConsoleApp kann man damit auch nichts anfangen. :wink:

Hast du nicht grundsätzlich das Problem, dass mehrere Instanzen deiner zu suchenden Anwendung (und damit des Fensters) existieren können?


Nein, in diesem Fall nicht. Es handelt sich um eine Anwendung, die nur einmal gestartet sein kann. Sie benutzt auch den FindWindow-Mechanismus. Wäre es anders, müsste man natürlich auch anders vorgehen.

Verwendet man unter Delphi pro Anwendung einen eigenen Klassennamen für das Hauptfenster, dann lassen sich mit FindWindow(Classname, nil) alle Instanzen einer bestimmten Anwendung finden. Da es in diesem Fall nur eine Instanz der Anwendung geben kann, hat man damit das richtige Handle gefunden und kann mit der Anwendung "reden". Unter Lazarus heißen alle Lazarusanwendungen 'Window' womit diese Möglichkeit leider nicht existiert.

Das ist das ganze Problem. Lazarus erzeugt Windows-Fenster einfach anders als Delphi. Mit Delphi ist die Abfrage ob eine Anwendung, die nur einmal laufen soll, schon läuft, auf diese Weise eben sehr einfach. Gleiches gilt, wenn man das Fensterhandle für andere Dinge benötigt (z.B.: PostMessage).

Bleibt halt die Frage warum die Lazarusentwickler Windows-Fenster mit einem nutzlosen Klassennamen versehen anstatt darüber dem Anwendungsentwickler eine Unterscheidungsmöglichkeit der verschiedenen Anwendungen zu ermöglichen? :mrgreen:

Eventuell mag dir auch dein Widgetset weiterhelfen (aber eher unwahrscheinlich).


Was genau ist denn ein Widgetset? Habe ich jetzt schon mehrmals gelesen... :oops:


Grüße,
Uwe


Uwe_9988
Beiträge: 30
Registriert: Fr 14. Jan 2011, 11:02

Re: FindWindow - Unterschied zu Delphi

Beitrag von Uwe_9988 »

Hallo Theo,

danke für die Erklärung. Du hast die Win32-API vergessen. :D

Mal 'ne andere Frage. Gibt es denn auch Lazarusbenutzer, die einfach nur Windowsanwendungen schreiben wollen?

Ich brauche doch für FindWindow gar keinen Ersatz unter Linux oder Mac. Allerdings möchte ich schon verstehen, warum sich eine Lazarus-Windows-Anwendung schon bei FindWindow so gänzlich anders verhält wie das entsprechende Delphi-Pendant.

Ich bin ja noch in der Phase wo ich mir ein Bild mache ob Lazarus für die Zwecke, die ich verfolge, überhaupt geeignet ist. Nichts gegen Lazarus, bitte nicht falsch verstehen. Ich habe den größten Respekt vor der Leistung der Lazarusentwickler.

Ich möchte nur abschätzen können, wie groß der Aufwand ist, wenn man mehr als nur ein "Hello World!" von Delphi nach Laz portieren muss. ;)

Viele Leute hören "Lazarus" und denken, dass man damit problemlos Delphiprogramme umschreiben kann. So auch mein Auftraggeber. :mrgreen:


Den Zahn werde ich ihm dann aber mal zumindest etwas lockern müssen...


Grüße,
Uwe

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: FindWindow - Unterschied zu Delphi

Beitrag von theo »

Uwe_9988 hat geschrieben:Ich brauche doch für FindWindow gar keinen Ersatz unter Linux oder Mac. Allerdings möchte ich schon verstehen, warum sich eine Lazarus-Windows-Anwendung schon bei FindWindow so gänzlich anders verhält wie das entsprechende Delphi-Pendant.


Eben darum, weil diese Funktionen Plattformspezifisch sind. Deshalb sind sie für Lazarus nicht von grosser Bedeutung.
Es gibt dafür jew. andere, plattformübergreifende Lösungen, wie z.B. eben http://wiki.lazarus.freepascal.org/UniqueInstance/de

Wie gut sich Delphi Programme übernehmen lassen hängt u.a. davon ab, wie viel Windows spezifischen Code sie enthalten.

Antworten