Entwickler-Ecke
Windows API - Alle Kindfenster auflisten
DerNetteNachbar - Fr 12.12.08 14:58
Titel: Alle Kindfenster auflisten
Hallo an euch alle, wie der Titel schon etwas verrät suche ich eine API Funktion die mir alle Fenster bzw. Handles auflistet die vom Top Level Fenster bzw. TOP Prozess aufgerufen wurden.
MfG
Nachbar
Delete - Fr 12.12.08 15:02
Wenn ich den Threadtitel ins Englische übersetze, komme ich auf EnumChildWindows ;).
DerNetteNachbar - Fr 12.12.08 15:06
Da bekomme ich leider alle Fenster die vom System aufgerufen wurden. Ich brauche nur die die von meiner Anwendung aufgerufen wurden.
Delete - Fr 12.12.08 15:10
Versteh ich nicht. Du hast das jetzt aber nicht mit EnumWindows verwechselt?
Zitat: |
The EnumChildWindows function does not enumerate top-level windows owned by the specified window, nor does it enumerate any other owned windows. |
DerNetteNachbar - Fr 12.12.08 15:13
Könnt ihr mir vielleicht ein kleines Beispiel aus dem Ärmel schütteln. Irgentwie ist des alles etwas verwirrend.
MfG
Nachbar
DerNetteNachbar - Fr 12.12.08 15:29
Irgentwie liefert mir diese Funktion EnumCHildWindows nichts als leere Strings zurück.
Delete - Fr 12.12.08 15:34
Wie verwendest Du sie denn? Meine Glaskugel ist gerade zum Polieren.
DerNetteNachbar - Fr 12.12.08 15:56
So verwenden ich diese Funktion:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| function EnumProc(wnd: HWND; Lines: TStrings): BOOL; stdcall; var buf, Caption: array[0..255] of char; begin Result := True; GetClassName(wnd, buf, SizeOf(buf) - 1); SendMessage(wnd, WM_GETTEXT, 256, Integer(@Caption)); Lines.Add(Format('ID: %d, ClassName: %s, Caption: %s', [GetDlgCtrlID(wnd), buf, Caption])); end;
procedure TForm1.Button1Click(Sender: TObject); begin ListBox1.Clear; EnumChildWindows(Application.Handle, @EnumProc, Integer(ListBox2.Items)); end; |
Delete - Fr 12.12.08 16:01
Lines wovon?
DerNetteNachbar - Fr 12.12.08 16:08
Vom Typ TString, als linken Parameter kann man dann das Ergebnis als string darstellen lassen.
Delete - Fr 12.12.08 16:11
Ach, das war ein Übergabeparameter, sry. Ersetz doch mal Application.Handle durch self.Handle.
DerNetteNachbar - Fr 12.12.08 16:14
Ja dann liefert mir die Funktion alle Objekte die auf der Form sind. Keine andere Formulare.
Delete - Fr 12.12.08 16:18
Du willst die Fenster Deiner Anwendung auflisten? Dann wäre EnumThreadWindows wohl eher die richtige Funktion.
DerNetteNachbar - Fr 12.12.08 16:23
So das ist die Funktion die ich verwende: trotzdem werden mir nur leere Strings zurückgeliefert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function EnumerateThreadWindows(Wnd: HWND; Data: lParam): BOOL; var WindowText: array[0..255] of char; WindowText1: PChar; begin GetWindowText(Wnd, WindowText, 255); Form1.ListBox1.Items.Add(WindowText); Result := True; end;
procedure TRetForm.Button1Click(Sender: TObject); begin EnumThreadWindows(GetCurrentThreadID, @EnumerateThreadWindows, 0); end; |
DerNetteNachbar - Fr 12.12.08 16:50
Hilft mir leider auch nicht weiter
Delete - Fr 12.12.08 16:51
Wie wäre es denn hiermit?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| function EnumerateThreadWindows(Wnd: HWND; Data: lParam): BOOL;stdcall; var WindowText: string; pid: integer; begin GetWindowThreadProcessID(Wnd,@pid); if IsWindowVisible(Wnd) and (pid = Data) then begin SetLength(WindowText,MAX_PATH); GetWindowText(Wnd, @WindowText[1], MAX_PATH - 1); SetLength(WindowText,StrLen(PChar(WindowText))); Form1.ListBox1.Items.Add(WindowText); end; Result := True; end;
procedure TForm1.Button1Click(Sender: TObject); var pid: integer; begin GetWindowThreadProcessID(Handle,@pid); EnumWindows(@EnumerateThreadWindows, pid); end; |
DerNetteNachbar - Fr 12.12.08 17:00
Ich glaub die Funktion ist etwas unausgereift, denn mir meldet Delphi ne Menge Fehler.
Delete - Fr 12.12.08 17:01
Unter Delphi 5 läuft es. Welche Fehler meldet Delphi denn?
DerNetteNachbar - Fr 12.12.08 17:06
Delphi-Quelltext
1:
| GetWindowThreadProcessID(Wnd,@pid); |
Doppeldeutiger Überladener Aufruf von dieser Funktion
Delete - Fr 12.12.08 17:13
Dann musst Du mal die Codevervollständigung in Anspruch nehmen oder eine gute Stunde warten, ich kann hier mit Delphi 5 nicht nachsehen.
DerNetteNachbar - Fr 12.12.08 17:27
Wie geht denn eine Codevervollständigung
Delete - Fr 12.12.08 17:29
Gib mal GetWindowThreadProcessID( ein und warte ein wenig oder drücke CTRL - SPACE. Dann sollte ein Hintfenster mit möglichen Parametern erscheinen.
DerNetteNachbar - Fr 12.12.08 17:32
Ahso das meinst du, da hab ich vorhin schon getan, leider kommen da beim 2ten. Parameter zwei Möglichkeiten in Frage (Cardinal und Pointer) und keins der beiden scheint zu klappen.
Delete - Fr 12.12.08 17:36
Und wenn Du das @-Zeichen weglässt?
DerNetteNachbar - Fr 12.12.08 17:44
Schon alles erdenkliche versucht, nichts klappt......welche uses Klausel sollte eigentlich eingebunden werden.
Hab den Verdacht ,dass das ich nicht die richtige Klausel drin habe.
Delete - Fr 12.12.08 17:47
Nächster Versuch:
Delphi-Quelltext
1:
| Windows.GetWindowThreadProcessID(Wnd,@pid); |
Delete - Fr 12.12.08 17:57
Ich hab jetzt gleich Feierabend und versuch es zu Hause unter Delphi 2007 nochmal.
DerNetteNachbar - Fr 12.12.08 17:59
Gut das klappt ;-), man man das war vielleicht eine schwere Geburt.
Ich danke vorallem dem DeddyH das er soviel Gedult mit mir hatte ;-)......
Ich versuche mich zu bessern und nicht soviele Fragen zu stellen.
MfG Nachbar
Delete - Fr 12.12.08 18:43
Mir ist da noch ein anderer Ansatz eingefallen *g*
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure ListOwnForms(const sl: TStrings; OnlyVisible: Boolean = True); var i: Integer; begin sl.BeginUpdate; try for i := 0 to Screen.FormCount - 1 do if Screen.Forms[i].Showing or not OnlyVisible then sl.Add(Screen.Forms[i].Caption); finally sl.EndUpdate; end; end; |
DerNetteNachbar - Sa 13.12.08 14:26
Eigentlich sollte es ja möglichst mit API Funktionen gehen, da ich auch DLL Aufrufe aus meinen Programm erkennen muss. Und soviel ich weiss werden Forms aus DLL nicht als Child Fenster angezeigt? Oder gibt es da etwa doch einen Kniff?
MfG
Delete - Sa 13.12.08 14:31
Ach, es geht um DLLs, das muss ich überlesen haben. IIRC hat die DLL ein anderes Prozesshandle als die aufrufende Instanz, das stimmt schon.
DerNetteNachbar - Sa 13.12.08 14:46
Und was heisst das jetzt für mich im konkreten?
Delete - Sa 13.12.08 14:53
Du müsstest dann nicht das eigene Prozesshandle übergeben, sondern das der DLL.
DerNetteNachbar - So 14.12.08 22:54
Und wie stelle ich das an?
jaenicke - So 14.12.08 23:23
Ich nehme an du lädst die DLL mit LoadLibrary, und die Funktion gibt dir das Handle der DLL zurück.
DerNetteNachbar - Mo 15.12.08 10:21
Nein ich lade die DLL statisch, sprich ich binde diese einfach per external Klausel ein. Ich wüsste jetzt nicht partou wie ich das Handle der DLL rauskriegen würde.
Delete - Mo 15.12.08 11:25
Wenn es Deine eigene DLL ist, könntest Du sie eine entsprechende Funktion exportieren lassen.
DerNetteNachbar - Mo 15.12.08 12:31
Ich muss von einer DLL einer anderen das Handle der DLL mitteilen.
jaenicke - Mo 15.12.08 13:34
Wenn du LoadLibrary auf eine bereits in dein Programm geladene DLL aufrufst bekommst du einfach das Handle und ein Referenzzähler wird um 1 erhöht (der dann bei FreeLibrary wieder um 1 reduziert wird, damit die DLL entladen wird, wenn du nicht mehr darauf zugreifst). Ich gehe davon aus, dass das auch bei statisch eingebundenen DLLs so funktioniert.
Es gibt natürlich auch direkte Möglichkeiten die geladenen DLLs durchzugehen, aber das dürfte die einfachste Lösung sein.
DerNetteNachbar - Mo 15.12.08 13:38
Wie kann ich denn eine DLL identifizieren, z.B. anhand des Namens? Brauche wie ich schon sagte das Handle während der Laufzeit. Mit FindWindow geht es wohl schlecht da ich kein Fenster in der DLL nun mal habe.
jaenicke - Mo 15.12.08 13:55
Ja, wenn du es mir LoadLibrary nicht machen willst, dann sollte EnumProcessModules das richtige sein.
DerNetteNachbar - Mo 15.12.08 14:49
Kannst du vielleicht ein Beispiel posten damit ich einen Blick dafür habe?
DerNetteNachbar - Mo 15.12.08 16:29
Geht es vielleicht etwas leichter?
jaenicke - Mo 15.12.08 16:57
Ich habe LoadLibrary ja bereits vorgeschlagen, ich habe das nicht getestet, gehe aber wie gesagt davon aus, dass das funktioniert. Einfacher geht es nun wirklich nicht. Hast du das denn einmal ausprobiert?
DerNetteNachbar - Mi 17.12.08 10:56
Ja danke mit loadlibrary hat es geklappt das Handle der DLL zu kriegen. Nun sende ich mittels SendMessage Textnachrichten von der DLL an das Programm und vom Programm an die DLL. Der erste Weg klappt ganz hervorragend nur der zweite will irgentwie nicht. Ich habe das mit diesem Beispiel von den Schweizern realisiert:
http://www.swissdelphicenter.ch/de/showcode.php?id=163
Irgentwas mach ich falsch da ich mit der DLL nicht empfangen kriege.
MfG
Nachbar
Moderiert von
Narses: Link in URL-Tags gesetzt
jaenicke - Mi 17.12.08 12:43
Naja, in der DLL hast du vermutlich kein Fenster? Das kann auch ein leeres sein, um das zu erstellen gibts eine API-Funktion. Aber Nachrichten kann man nur mit Fensterhandles austauschen.
Oder wenn doch wie sieht dort denn der Code aus?
Aber wozu SendMessage? Hat das einen tieferen Sinn?
Delete - Mi 17.12.08 12:47
Nochmal zum Verständnis: ist das Deine eigene DLL oder eine fremde?
DerNetteNachbar - Mi 17.12.08 13:12
Das ist meine eigene DLL und ich habe auch Fenster drin die aufgerufen werden. Mit der oben erwähnten Funktion Receive empfange ich den String von der DLL. Nur leider klappt eben derselbe Mechanismus nicht wenn man zu dem Handle der DLL sendet. Übrigens in der SendMessage hab ich eben den String der gesendet wird, als eigene Message deklariert.
Delete - Mi 17.12.08 13:16
Dann frage ich mich aber, wieso Du die Kommunikation zwischen Anwendung und DLL über Messages abwickelst und nicht über exportierte DLL-Funktionen.
jaenicke - Mi 17.12.08 13:17
Ich habe sowas nie ausprobiert, aber du könntest ja direkt an die einzelnen Fenster schicken. Schließlich hast du die ja auflisten lassen.
Und das ist auch der Titel dieses Threads. Deine Fragen jetzt haben damit ja nicht mehr etwas zu tun, oder? Denn dieses Problem war ja gelöst.
Trotzdem frage ich mich warum du überhaupt SendMessage benutzt, das ist doch unnötig kompliziert. :gruebel:
DerNetteNachbar - Mi 17.12.08 13:28
Stimmt, sorry bin etwas vom Thema abgewischen. Theoretisch währe das Problem hiermit gelöst. Danke euch beiden für euere tatkräftige Unterstützung.
MfG
Nachbar
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!