Autor Beitrag
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 08.08.17 05:42 
Mein letztes Codebeispiel war auch sehr schlampig und musste schlußendlich scheitern. Das tut mir leid.
Das Problem besteht im Fenster-Handle, welches jedes Mal von neuen ermittelt und zugewiesen wird. Das läuft darauf hinaus, dass der (temporäre) Handle-Wert, sofern nichts dazwischen kommt, unverändert bleibt.
Man muss also beim Filtern der Fenster sogleich auch die momentanen Fenster-Handle-Werte mitschreiben:

ausblenden volle Höhe 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:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
procedure GetSpecificWindowCaption(AList: TStrings; SubText: string);
  function GetAllWindows(hWnd: HWND; AList: TStrings): Boolean; stdcall;
  var
    captionLength: Word;
    wndCaption: string;
  begin
    captionLength := GetWindowTextLength(hWnd);
    SetLength(wndCaption, captionLength);
    GetWindowText(hWnd, PChar(wndCaption), captionLength);
    AList.AddObject(wndCaption, TObject(hWnd)); // <-- Fenstertitel und zugehörige Handle mitschreiben  
    result := true;
  end;
var
  tmp: TStringList;
  i: Integer;
begin
  if (AList <> niland (SubText <> ''then
  begin
    tmp := TStringList.Create;
    try
      EnumWindows(@GetAllWindows, Integer(tmp));
      AList.BeginUpdate;
      for i := 0 to tmp.Count - 1 do
        if Pos(UpperCase(SubText), UpperCase(tmp[i])) <> 0 then
          AList.Add(IntToStr(HWND(tmp.Objects[i])));
      AList.EndUpdate;
    finally
      tmp.Free;
    end;
  end;
end;

procedure SendText(const CaptionSub, ControlClassName, Msg: string);
var
  i: Integer;
  hnd: HWND;
  list: TStringList;
begin
  list := TStringList.Create;
  try
    GetSpecificWindowCaption(list, CaptionSub);
    for i := 0 to List.Count - 1 do
    begin
      hnd := FindWindowEx(StrToInt(list[i]), 0, PChar(ControlClassName), nil);
      SendMessage(hnd, WM_SETTEXT, 0, Integer(PChar(Msg)));
    end;
  finally
    list.Free;
  end;
end;

// Aufruf
begin
  SendText('SynEdit''TMemo''Neuer TMemo Text in allen Fenstern mit dem Caption-Inhalt SYNEDIT');
end;

PS: Wenn dein Projekt (T)SynEdit heißt und du außerdem die TSynEdit Komponente darin nutzt, sind Probleme vorgrogrammiert.

Warum es mit der TJvWideHLEditor Komponente nicht so funktioniert, müsste man es sich genauer anschauen. Ihren Ursprung hat sie im TCustomControl, ebenso wie die bereits angesprochene TSynEdit Komponente.
Auf folgendes müsste man dabei Rücksicht nehmen:
WM_SETTEXT hat folgendes geschrieben:
The return value is TRUE if the text is set. It is FALSE (for an edit control), LB_ERRSPACE (for a list box), or CB_ERRSPACE (for a combo box) if insufficient space is available to set the text in the edit control. It is CB_ERR if this message is sent to a combo box without an edit control.
...
LB_ERRSPACE, CB_ERRSPACE = -2
CB_ERR = -1

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Di 08.08.17 18:20 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Man muss also beim Filtern der Fenster sogleich auch die momentanen Fenster-Handle-Werte mitschreiben:
Mit meiner Komponente TWideHLEditorX funktioniert es immer noch nicht, wobei ich dazu sagen muss, dass diese Kompenenten dynamisch zur Laufzeit erzeugt werden.
Mit TMemo oder TEdit wird der Text zwar in allen Instanzen eingefügt, aber jeweils nur in die zuerst erstellte Komponente, und dann auch nur, wenn diese direkt auf der Form liegt. Wenn sie auf einer Toolbar oder auf einem Panel liegt, klappt es nicht.

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
PS: Wenn dein Projekt (T)SynEdit heißt und du außerdem die TSynEdit Komponente darin nutzt, sind Probleme vorgrogrammiert.
Ich verwende u.a. aus genau diesem Grund nicht TSynEdit, sondern eine von TJvWideHLEditor abgeleitete Komponente: TWideHLEditorX!

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Warum es mit der TJvWideHLEditor Komponente nicht so funktioniert, müsste man es sich genauer anschauen. Ihren Ursprung hat sie im TCustomControl, ebenso wie die bereits angesprochene TSynEdit Komponente.
Weil dynamisch erzeugt? Obwohl: Parent ist Form1...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 08.08.17 19:15 
Zitat:
Mit TMemo oder TEdit wird der Text zwar in allen Instanzen eingefügt, aber jeweils nur in die zuerst erstellte Komponente, und dann auch nur, wenn diese direkt auf der Form liegt. Wenn sie auf einer Toolbar oder auf einem Panel liegt, klappt es nicht.

Ich kann nicht so gut hellsehen oder vermuten, wo du deine Controls genau hast, oder gar wieviele. :twisted:
Man kann es natürlich auf deine Gegebenheit anpassen, wenn du bereit bist sie zu nennen. :mrgreen:
Noch besser: Ich lasse dir den Vortritt und du darfst Verbesserungen daran durchführen, als Übungszweck.

Damit du nicht ganz unvorbereitet bist: Wenn sich ein Control z.B. auf einem Panel befindet, dann musst du zunächst das Panel mit FindWindowEx() suchen, den Handle-Wert dir merken, dann erneut mit FindWindowEx() nach dem besagten Control suchen, wobei dieses FindWindowEx() im ersten Parameter den Handle-Wert des Panels bekommt.
Wenn du aber nicht nach dem erst-möglichen Control suchst, sondern gezielt ein bestimmtes, dann musst du dem FindWindowEx() im vierten Parameter die Caption übergeben, wie z.B. "Edit3".
Der Rest ist wie gehabt. ;)

Zitat:
Ich verwende u.a. aus genau diesem Grund nicht TSynEdit, sondern eine von TJvWideHLEditor abgeleitete Komponente: TWideHLEditorX!

In erster Linie ist mir TJvWideHLEditor zu exotisch, da sie schonmal an die 8-12 Vererbungen intus hat.
Dann setzt sie außerdem voraus, dass JEDI installiert sein muss, nicht nur die JVCL, sondern vorher schon die JCL.
Außerdem reagiert sie nicht auf die Nachricht WM_SETTEXT. Muss man sich deswegen auch noch kümmern.

Wenn es Probleme mit den deckungsgleichen Klassennamen gibt, wie in deinem Projekt zu TSynEdit, dann nenn' deine Hauptklasse z.B. TgaSynEdit und alles ist gut.
Ich mach' das bei mir nicht viel anders, aus genau diesem Grund!

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)

Für diesen Beitrag haben gedankt: galagher
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Di 08.08.17 19:37 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Ich kann nicht so gut hellsehen oder vermuten, wo du deine Controls genau hast, oder gar wieviele. :twisted:
Man kann es natürlich auf deine Gegebenheit anpassen, wenn du bereit bist sie zu nennen. :mrgreen:
War ja kein Vorwurf, nimm's nicht persönlich!

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Noch besser: Ich lasse dir den Vortritt und du darfst Verbesserungen daran durchführen, als Übungszweck.
Damit wären wir bei:
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Wenn sich ein Control z.B. auf einem Panel befindet, dann musst du zunächst das Panel mit FindWindowEx() suchen, den Handle-Wert dir merken, dann erneut mit FindWindowEx() nach dem besagten Control suchen, wobei dieses FindWindowEx() im ersten Parameter den Handle-Wert des Panels bekommt.
Wenn die "Ziel"-Komponente auf einer weiteren Komponente liegt, und - aus welchem Grund auch immer - diese wiederum auf einer weiteren Komponente, muss ich a) wissen, nach welchen Komponenten ich suchen muss und b) die Suche für jede der Komponenten durchführen, bis ich bei der Komponente angelangt bin, die ich eigentlich meine! :eyecrazy: Naja... :?

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Wenn es Probleme mit den deckungsgleichen Klassennamen gibt, wie in deinem Projekt zu TSynEdit, dann nenn' deine Hauptklasse z.B. TgaSynEdit und alles ist gut.
Es gibt keine Probleme mit TSynEdit, das kommt in meinem Programm gar nicht vor!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 08.08.17 20:07 
Ich muss mal Dampf ablassen :autsch: Das genügt :lol:

Das Prinzip funktioniert folgendermaßen: Ein Fenster muss erst einmal gefunden werden, z.B. mit FindWindow(). Das hast du aber schon mit der Funktion GetSpecificWindowCaption() verwirklicht.

Jetzt kommt die Suche nach den Controls: Liegen diese Verschachtelt auf/in mehreren Panels, dann muss mit FindWindowEx() jenes PanelA gesucht werden, welches sich direkt auf der Form befindet.
Der Rückgabewert dieser Funktion ist ein Handle zum PanelA. Den muss man sich merken.
Wenn ein PanelB darauf liegt, denn ruft man erneut FindWindowEx() auf, wobei das PanelA-Handle im 1. Parameter übergeben bekommt.
Liegt dann jenes Control auf PanelB, muss erneut FindWindowEx() aufgerufen werden, welches im 1.Parameter das PanelB-Handle übergeben bekommt.
Damit wäre das erst-mögliche Control gefunden. Soll es aber ein ganz bestimmtes Control sein, gibt man dem vorherigen FindWindowEx() im 4. Parameter die Caption mit. In dem Fall, wäre es der genaue Name des Controls, wie z.B. "Edit3".

Ganz kurz gesagt: Mit FindWindowEx() suchst du von der Form weg, die nächst-untere Ebene auf, bis du an dein Ziel angelangst.


TSynEdit kannst du ruhig installiert. Damit gibt es keinerlei Probleme. Sie ist ebenso kostenlos, du kannst ebenso in den Quelltext einsehen, und sie reagiert auch auf die WM_SETTEXT Nachricht. :dance2:
Du kannst sie ebenso gern Ableiten, wenn du deine Erweiterungen realisieren möchtest.

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Mi 09.08.17 21:11 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Ganz kurz gesagt: Mit FindWindowEx() suchst du von der Form weg, die nächst-untere Ebene auf, bis du an dein Ziel angelangst.
Erst dachte ich, wozu soll ich mir die ganze Arbeit machen? Aber jetzt werde ich mich wohl doch damit beschäftigen! Deine Lösung hat was! Ich wünschte nur, man könnte das allgemeiner halten, also statt nach TPanel zu suchen, sucht man nach TObject oder so ähnlich. Mal sehen, was ich rausfinde! Wird aber dauern.

Wenn ich es mit meiner Lösung, also mit Prozedur ReceiveData, mache, kann ich dort rein schreiben, was immer ich will. Nachteil: Die Fenster müssen zwingend eine Prozedur haben, die als Empfänger fungiert. Fenster, bei denen zwar die Caption stimmt, die aber keinen "Empfangsteil" haben, machen klarerweise nichts.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 10.08.17 00:32 
Man könnte es schon allgemeiner halten, wenn man sich den Zugriff zum Hauptfenster verschafft. Dann geht man mit .ControlCount alle Controls durch und sucht nach einem bestimmten Typen/Klasse:

ausblenden 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:
24:
25:
26:
27:
procedure SendText2(const CaptionSub, ControlClassName, Msg: string);
var
  i, j: Integer;
  list: TStringList;
  wndCtrl: TWinControl;
  hnd: HWND;
begin
  list := TStringList.Create;
  try
    GetSpecificWindowCaption(list, CaptionSub);
    for i := 0 to list.Count - 1 do
    begin
      hnd := StrToInt(list[i]);
      wndCtrl := FindControl(hnd);
      for j := 0 to wndCtrl.ControlCount - 1 do
      begin
        if string(wndCtrl.Controls[j].ClassName) = ControlClassName then
        begin
          hnd := TWinControl(wndCtrl.Controls[j]).Handle;
          SendMessage(hnd, WM_SETTEXT, 0, Integer(PChar(Msg)));
        end;
      end;
    end;
  finally
    list.Free;
  end;
end;

Das setzt den Text auch überall rein, wie z.B. in allen TMemo, die sich im jenen Fenster befinden, nur ... scheint es Probleme zu geben, wenn die Fenster identisch sind.
Ich denk' morgen darüber nach. Dafür bin ich jetzt viel zu K.O.

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Do 10.08.17 17:58 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Man könnte es schon allgemeiner halten, wenn man sich den Zugriff zum Hauptfenster verschafft. Dann geht man mit .ControlCount alle Controls durch und sucht nach einem bestimmten Typen/Klasse:
Es funktioniert nicht, auch nicht mit if wndCtrl.Controls[j].ClassNameIs(ControlClassName) then statt if string(wndCtrl.Controls[j].ClassName) = ControlClassName then. (Hier kann man string doch weglassen!)
Das Control wird nur gefunden, wenn es direkt auf dem Fenster liegt. Wenn also ein Memo auf einem Panel liegt, welches auf dem Fenster liegt, dann klappt es mit dem Panel, wenn man 'TPanel' angibt: Die Caption ändert sich. Wenn man 'TMemo' angibt, tut sich mit dem Memo aber nichts.

Ich verstehe den Code, und eigentlich müsste ja alles stimmen...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 10.08.17 18:02 
Hast du den Code nun wirklich verstanden?

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Do 10.08.17 18:35 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Hast du den Code nun wirklich verstanden?
Ich denke schon, und mir fällt kein Fehler auf.
Mit Kommentaren versehen:
ausblenden 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:
24:
25:
26:
27:
procedure SendText2(const CaptionSub, ControlClassName, Msg: string);
var
  i, j: Integer;
  list: TStringList;
  wndCtrl: TWinControl;
  hnd: HWND;
begin
  list := TStringList.Create;
  try
    GetSpecificWindowCaption(list, CaptionSub);  //Liste aller in Frage kommender Fenster samt Handles erstellen
    for i := 0 to list.Count - 1 do
    begin
      hnd := StrToInt(list[i]);  //Handle zuweisen
      wndCtrl := FindControl(hnd);  //Control suchen und zuweisen
      for j := 0 to wndCtrl.ControlCount - 1 do  //Alle Controls des Fensters durchgehen
      begin
        if string(wndCtrl.Controls[j].ClassName) = ControlClassName then  //Wenn Classname des Controls mit dem des 
        begin                                                         //angegebenen Controls übereinstimmt, dann
          hnd := TWinControl(wndCtrl.Controls[j]).Handle;             //Handle des Controls an hnd zuweisen und
          SendMessage(hnd, WM_SETTEXT, 0, Integer(PChar(Msg)));       //senden. Bei mehreren Fenstern Zugriffsverletzung.
        end;
      end;
    end;
  finally
    list.Free;
  end;
end;

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!

Für diesen Beitrag haben gedankt: Frühlingsrolle
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 10.08.17 19:02 
Sehr gut! Der 3. Kommentar sollte eher lauten: "Fenster suchen und zuweisen".
Genau, und am Ende: "Bei mehreren Fenstern Zugriffsverletzung", gilt es zu beheben/umgehen. Das Problem stellt FindControl() dar, und ich hätte gern gewusst, warum?!

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Do 10.08.17 19:16 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Das Problem stellt FindControl() dar, und ich hätte gern gewusst, warum?!
Ich auch, aber vor allem möchte ich wissen, warum nur Controls gefunden werden, die auf dem Fenster liegen!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 10.08.17 19:47 
Zitat:
vor allem möchte ich wissen, warum nur Controls gefunden werden, die auf dem Fenster liegen!

Kurz ausholen: TControl ist ein Nachfahre von TComponent. Der Unterschied ist, dass das TControl ein sichtbares! Steuerelement ist, welches z.B. ein Eingabefeld (TEdit) oder ein Fenster (TForm) zur Laufzeit darstellt.
Das TComponent ist dafür nicht sichtbar, läuft im Hintergrund, ohne dass man etwas davon merkt, wie z.B. der TTimer oder TfrDrive. :D

Gibt man der Funktion FindControl() ein Handle eines gültigen Controls mit (TForm ist z.B. so eins), dann ist der Rückgabewert dieser Funktion ein Control mit jenen mitgegebenen Handle. In dem Beispiel gibt die Funktion ein TForm zurück, welches die Caption "SynEdit" zum Teil enthält.
Das könnte genauso gut jedes andere Control sein, also ein Nachfahre von TControl!

So, weil Controls auf Controls liegen können, gibt es eine Eigenschaft namens .ControlCount. Ebenso gibt es die Eigenschaft .ComponentCount.
Die Werte können sich unterscheiden, denn ein Control ist u.a. eine Komponente (TComponent). Eine Komponente ist aber kein Control!
Geht man nun den Zähler durch, kann man mit der Eigenschaft .Controls[i] auf alle Controls zugreifen, die auf dem Ausgangs-Control zur Verfügung stehen, TPanel inklusive, ist ja auch ein (sichtbares) Control. ;)

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Do 10.08.17 20:50 
Ich möchte den Code so allgemein gestalten, dass ich ihn wieder verwenden kann, ohne ihn jedesmal anpassen zu müssen. Ein oder mehrere TEdit(s) zB. kann/können ohne Weiteres auf einem TPanel liegen.

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Geht man nun den Zähler durch, kann man mit der Eigenschaft .Controls[i] auf alle Controls zugreifen, die auf dem Ausgangs-Control zur Verfügung stehen, TPanel inklusive, ist ja auch ein (sichtbares) Control. ;)
Kann man offensichtlich nicht, denn es werden nur solche Controls berücksichtigt, die direkt auf der Form liegen.
"auf alle Controls, die auf dem Ausgangs-Control zur Verfügung stehen" - das bedeutet, es müsste funktionieren. Wenn ich also TEdit angebe, und es liegt ein TEdit auf einem TPanel, warum funktioniert es dann nicht? Steht doch eindeutig da:
ausblenden Delphi-Quelltext
1:
2:
3:
for j := 0 to wndCtrl.ControlCount - 1 do  //Alle Controls des Fensters durchgehen
begin
  if string(wndCtrl.Controls[j].ClassName) = ControlClassName then


wndCtrl.Controls[j] ist doch das mit Index j "gelistete" TControl von wndCtrl, also von einem TWinControl. Wo es rumliegt, muss doch egal sein! Ich verstehe das nicht.

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 10.08.17 21:07 
Das gibt's doch nicht! Na schön, dann ersetz' ControlCount durch ComponentCount, und Controls[i] durch Components[i].

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Sa 12.08.17 07:17 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Das gibt's doch nicht! Na schön, dann ersetz' ControlCount durch ComponentCount, und Controls[i] durch Components[i].
Das habe ich zwar gemacht, aber dabei vergessen, auch
hnd := TWinControl(wndCtrl.Controls[j]).Handle; anzupassen, es also zu
hnd := TWinControl(wndCtrl. Components[j]).Handle; zu ändern, und natürlich hat das dann nicht funktioniert ("Listenindex außerhalb des gültigen Bereichs"). :oops:

Bleibt noch die Zugriffsverletzung bei mehreren Fenstern zu lösen!

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Sa 12.08.17 10:25 
Bist du sicher, dass es an FindControl liegt? Die Zugriffsverletzung tritt erst bei SendMessage auf:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
for j := 0 to wndCtrl.ComponentCount - 1 do  //Alle Components des Fensters durchgehen
begin
  if wndCtrl.Components[j].ClassName = ControlClassName then
  begin
    hnd := TWinControl(wndCtrl.Components[j]).Handle;
    SendMessage(hnd, WM_SETTEXT, 0, Integer(PChar(Msg)));  //<-- Bei zwei Fenstern hält Delphi das Programm, wenn ich hier einen Haltepunkt setze, 2x an
  end;
end;

Alles bis zum SendMessage funktioniert also.

Andererseits kann man die Fehlermeldung verhindern, indem man wndCtrl auf nil überprüft, was mir sagt, es legt also doch an FindControl: Da ist also 1x etwas an wndCtrl zugewiesen, 1x nicht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
hnd := StrToInt(list[i]);  //Handle zuweisen
wndCtrl := FindControl(hnd);  //Control suchen und zuweisen
if wndCtrl <> nil then
  for j := 0 to wndCtrl.ComponentCount - 1 do  //Alle Components des Fensters durchgehen

Dennoch funktioniert es nur bei jener Instanz, aus der der Code aufgerufen wurde.
Ratlosigkeit macht sich breit...

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 15.08.17 07:27 
Zitat:
Bist du sicher, dass es an FindControl liegt? Die Zugriffsverletzung tritt erst bei SendMessage auf:

Jopp, denn ab dem 2. Durchlauf ist das Objekt wndCtrl gleich nil. Das ist kein Fehler in dem Sinne, sondern nur ein Zustand. Somit kann auch nicht auf die Controls des Fensters (= nil) zugegriffen werden -> Handle liefert 0 -> SendMessage() schlägt mit solch einem Handle fehl.

Zitat:
Dennoch funktioniert es nur bei jener Instanz, aus der der Code aufgerufen wurde.

Genau, das meinte ich mit, es gibt ein Problem mit der Methode.

Die Lösung wäre z.B. mit EnumChildWindows() an die Controls zu kommen, oder wie bereits erwähnt, mit FindWindowEx() alle Controls durchgehen und gegen den gesuchten Typ/Klasse prüfen.
In beiden Fällen gibt man im 1. Parameter das Handle des Anwendung-Fensters mit.

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)
galagher Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2119
Erhaltene Danke: 42

Windows 7 64 Bit
Delphi XE2 Starter, Delphi 10.1 Starter
BeitragVerfasst: Mi 16.08.17 18:21 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Die Lösung wäre z.B. mit EnumChildWindows() an die Controls zu kommen, oder wie bereits erwähnt, mit FindWindowEx() alle Controls durchgehen und gegen den gesuchten Typ/Klasse prüfen.
Aber in Prozedur GetSpecificWindowCaption wird doch schon EnumWindows verwendet! Das erstellt doch schon eine Liste aller gefundenen Fenster samt deren Handles: AList.AddObject(wndCaption, TObject(hWnd)); // <-- Fenstertitel und zugehörige Handle mitschreiben

_________________
gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1582
Erhaltene Danke: 286

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Mi 16.08.17 18:26 
Richtig, in der GetSpecificWindowCaption() Methode haben wir die Funktion EnumWindows() aufgerufen. EnumChildWindows() ist wiederum etwas anderes, wie der Name schon sagt.

_________________
„Wo andere blind der Wahrheit folgen, denk daran ... Nichts ist wahr!" (Assassin's Creed I-II)

Für diesen Beitrag haben gedankt: galagher