Autor Beitrag
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Di 20.07.04 15:09 
Hallo!

Ich benutze die folgende Procedure um mir alle Fenstertitel in eine Stringlist einfügen zu lassen:
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:
28:
29:
30:
Function EnumWindowsToStrings (aStrings: tStrings): Boolean;

    Function EnumWindowsProc (aHandle: HWND; aList: tStrings): Bool; stdcall; export;
    Var
      Title: Array[0..255] Of Char;
    Begin
      EnumWindowsProc := True;
      If GetWindowText (aHandle, @Title, 255) > 0 Then
        If IsWindowVisible (aHandle) And (String (Title) <> '') Then
          If aList.Add (String (Title)) = -1 Then
            ;
    End;

Begin
  EnumWindowsToStrings := False;

  Assert (Assigned (aStrings));
  If Not Assigned (aStrings) Then
    Exit;

  aStrings.BeginUpdate;
  Try
    If Not EnumWindows (@EnumWindowsProc, Integer (aStrings)) Then
      Exit;
  Finally
    aStrings.EndUpdate;
  End;

  EnumWindowsToStrings := True;
End;

Wenn ich diese Funktion ganz normal in meiner Anwendung aufrufe klappt auch alles perfekt. Wenn ich allerdings diese Funktion innerhalb eines Threads (in der überschriebenen Execute Methode) ausführe funktioniert es nicht. Die Funktion EnumWindows wird zwar aufgerufen aber danach passiert nichts mehr. Laut dem Debugger wird auch ein paar mal die EnumWindowsProc Procedure aufgerufen.

Woran kann das liegen?

Gruß
Tino
maxk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1696
Erhaltene Danke: 1

Win XP, Debian Lenny
Delphi 6 Personal
BeitragVerfasst: Di 20.07.04 15:17 
Also bei mir funktioniert's mit deinem Code! //Edit: Und zwar mit TListBox.Items

_________________
Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.


Zuletzt bearbeitet von maxk am Di 20.07.04 15:22, insgesamt 1-mal bearbeitet
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Di 20.07.04 15:20 
Hallo!

Ich denke, das hängt davon ab, was für einen TStrings-Nachfahren du da übergibst. Wenn du z.B. Memo.Lines übergibst, so ist das fatal, denn sämtliche Beeinflussungen von Steuer-Elementen wie ein Memo, eine Listbox etc. sind nicht threadsicher und müssen daher per Synchronize mit dem VCL-Hauptthread synchronisiert werden.

Edit: @MaxK: Hast du es in einem separaten Thread aufgerufen?

Cu,
Udontknow
Tino Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Di 20.07.04 15:27 
Ich habe tStringList benutzt. Ich benutze also keine VCL Komponente.

So sieht die Implementierung von Exceute des Threads aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
Procedure tTestThread.Execute;
Var
  SL: tStringList;
Begin
  fStop := False;

  SL := tStringList.Create;
  Try

    {...}

        SL.Clear;
        If EnumWindowsToStrings (SL) Then
          ;

    {...}

  Finally
    SL.Free;
  End;
End;

Gruß
Tino
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Di 20.07.04 15:37 
Also, bei mir funktioniert da alles, mein gesetzter Breakpoint bei SL.Free wird problemlos angesprungen, und zu diesem Zeitpunkt beinhaltet SL auch tatsächlich die Bezeichnungen der Fenster.

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:
procedure TForm1.Button1Click(Sender: TObject);
var T:TTestThread;
begin
  T:=TTestThread.Create(True);
  T.FreeOnTerminate:=True;
  T.Resume;
end;

{ TTestThread }

Procedure tTestThread.Execute;
Var
  SL: tStringList;
Begin
  SL := tStringList.Create;
  Try
    SL.Clear;
    EnumWindowsToStrings (SL);
  Finally
    SL.Free;
  End;
End;


Der Knackpunkt ist: Wie gibst du denn die Sachen dann zurück an den Haupt-Thread, der damit ja bestimmt was anfangen soll (darstellen)?
Tino Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Do 22.07.04 09:42 
So, gestern Abend habe ich nur rausgefunden woran es lag. Im Testprogramm habe ich direkt in der Projektdatei (dpr) das Threadobjekt initialisiert und gestartet. Da dort noch kein Application.Run aufgerufen wurde funktionierte das ganze tThread Objekt nicht wie erwartet. :?

Danke für Eure Antworten!

Gruß
Tino
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Do 22.07.04 10:20 
Nutzt du evtl. die Synchronize-Routine? Dann ist es nämlich klar, Synchronize wartet, bis der VCL-Haupt-Thread erneut in seine ProcessMessages-Routine gelangt (und das tut er nur, wenn Application.Run aufgerufen wurde).

Cu,
Udontknow
maxk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1696
Erhaltene Danke: 1

Win XP, Debian Lenny
Delphi 6 Personal
BeitragVerfasst: Do 22.07.04 10:36 
Tino hat folgendes geschrieben:
Da dort noch kein Application.Run aufgerufen wurde funktionierte das ganze tThread Objekt nicht wie erwartet. :?
Komisch ich habe den Thread in FormCreate gestartet, das geschieht doch eigentlich auch für Application.Run, oder? Aber in Zusammenhang mit Udontknows Antwort würde es logisch klingen

_________________
Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
Tino Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: So 25.07.04 20:24 
Udontknow hat folgendes geschrieben:
Nutzt du evtl. die Synchronize-Routine? Dann ist es nämlich klar, Synchronize wartet, bis der VCL-Haupt-Thread erneut in seine ProcessMessages-Routine gelangt (und das tut er nur, wenn Application.Run aufgerufen wurde).

Sorry, wegen der späten Antwort. Ja, ich habe Synchronize-Objekte benutzt. Und beim Debuggen war auch zu sehen das dort irgendetwas nicht stimmt. Ich denke also du hast recht :-)

Danke für die Aufklärung!

Gruß
Tino