Autor Beitrag
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: So 05.02.06 17:11 
Hi @all,

ich habe irgendwie ein Speicherzugriffsproblem in meinem Code. Er bekommt das nicht hin mit dem erstelltem Array zu arbeiten bzw. die Größe des Array zu ermitteln. Wenn ich die markierten Zeilen in eine extra Procedur packe (extra Button) funktioniert es auch ordentlich, aber nicht zusammen hängend (leider) :(.

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:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  TFensterInfo=record
    Handle: HWND;
    Caption: String;
  end;

var
  Form1: TForm1;
  FensterInfo: array of TFensterInfo;

implementation

{$R *.dfm}

Function EnumWindowsProc(Wnd: HWND): BOOL; stdcall;
var
  Capt: Array [0..128of Char;
begin
  Result:=true;
  if IsWindowVisible(Wnd) and
     ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0or
      (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT))=GetDesktopWindow)) and
     ((GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW)=0)
  then
  begin
    SendMessage(Wnd, WM_GETTEXT, Sizeof(Capt), integer(@Capt));
    SetLength(FensterInfo, length(FensterInfo)+1);
    FensterInfo[High(FensterInfo)].Caption:=String(Capt);
    FensterInfo[High(FensterInfo)].Handle:=Wnd;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
begin
  SetLength(FensterInfo, 0);
  EnumWindows(@EnumWindowsProc, 0);
  Form1.ListBox1.Items.Clear;
  for i:=0 to High(FensterInfo) do
  begin
    Form1.ListBox1.Items.Add(FensterInfo[i].Caption)
  end;

end;

end.


So hier dagegen funktioniert es:

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:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
unit Unit1;
 
interface 
  
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls, ExtCtrls;
 
type
  TForm1 = class(TForm) 
    Button2: TButton;
    ListBox1: TListBox;
    procedure Button2Click(Sender: TObject); 
  private 
    { Private-Deklarationen } 
  public 
    { Public-Deklarationen } 
  end
 
type 
  TFensterInfo=record 
    Handle: HWND; 
    Caption: String
  end
 
var 
  Form1: TForm1; 
  FensterInfo: array of TFensterInfo;
  lengthvar: integer = 0;
 
implementation 
 
{$R *.dfm}
 
Function EnumWindowsProc(Wnd: HWND): BOOL; stdcall
var 
  Capt: Array [0..128of Char; 
begin 
  Result:=true; 
  if IsWindowVisible(Wnd) and 
     ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0or 
      (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT))=GetDesktopWindow)) and
     ((GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW)=0
  then 
  begin
    SendMessage(Wnd, WM_GETTEXT, Sizeof(Capt), integer(@Capt));
    SetLength(FensterInfo, length(FensterInfo)+1);
    inc(lengthvar);
    FensterInfo[High(FensterInfo)].Caption:=Capt;
    FensterInfo[High(FensterInfo)].Handle:=Wnd;
  end;
end
 
procedure TForm1.Button2Click(Sender: TObject);
var 
  i: integer;
begin
  lengthvar := 0;
  SetLength(FensterInfo, 0);
  EnumWindows(@EnumWindowsProc, 0);
  Form1.ListBox1.Items.Clear;
  for i := 0 to lengthvar do
  begin
    Form1.ListBox1.Items.Add(FensterInfo[i].Caption);
  end
end;
 
end.

Bei dieser 2. Variante ist nur noch eine globale Variable hinzugefügt, damit der Befehl High wegfällt ;).

Wisst ihr woran das Problem liegt? Und kann man irgendwie auch machen, dass der Fenstertitel auch über eine Länge von 128 Bytes ausgelsen wird (also mit einer unbegrenzten Länge)?
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Mo 06.02.06 10:54 
Hallo,

ich habe es mal im CPU-Debugger angesehen.
In der ersten Version wird die Adresse des dynamischen Array in dem Register EDI gespeichert ist.
Aber EDI ist nach dem Aufruf von der EnumWindows(@EnumWindowsProc, 0) = 0.
Ich meine nach isvisible war EDI 0.
Damit wird bei dem Aufruf von High das variable Arra auf $0 gesucht wo es nicht ist und nie war.

Da hat Der compiler falsch gedacht, dass EDI nicht in der anderen procedure benutzt wird.
Die >zweite< Frage solltest Du nochmals stellen ;-)

Gruss Horst
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Mo 06.02.06 11:23 
Die Funktion high liefert den größten Wert im Bereich des Indextypes des Array. So steht es in der Hilfe.
D.h. dass in deinem Fall die High immer 128 liefert.

Mit

ausblenden Delphi-Quelltext
1:
2:
3:
    SetLength(FensterInfo, length(FensterInfo)+1);  
    FensterInfo[length(FensterInfo) - 1].Caption:=String(Capt);  
    FensterInfo[length(FensterInfo) - 1].Handle:=Wnd;


sollte das besser klappen.

Beste Grüße
Tastaro
Heiko Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Mo 06.02.06 20:47 
So nochmal zur Frage die ich vlt. nicht gut genug ausgedrückt habe ;). Und zwar will ich die Begrenzung aufheben die hier besteht (ich markiere es mal):

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function EnumWindowsProc(Wnd: HWND): BOOL; stdcall;
var
  Capt: Array [0..128of Char;
begin
  Result:=true;
  if IsWindowVisible(Wnd) and
     ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0or
      (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT))=GetDesktopWindow)) and
     ((GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW)=0)
  then
  begin
    SendMessage(Wnd, WM_GETTEXT, Sizeof(Capt), integer(@Capt));
    SetLength(FensterInfo, length(FensterInfo)+1);
    FensterInfo[High(FensterInfo)].Caption:=String(Capt);
    FensterInfo[High(FensterInfo)].Handle:=Wnd;
  end;
end;


Wie man sieht wird an der 2. markierten Stelle nur max. 129 Bytes zurückgegeben, da das Array nicht größer ist. Kann dort die Besczhränkung auf die 129 Bytes aufheben?

@Horst_H: Das mag sein (in der Art hatte ich es schon vermutet), aber ich kann mir nicht erklären warum dann der folgende Quelltext Problemlos funktioniert, wenn ich nach ein ander die Buttons drücke:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.Button2Click(Sender: TObject);
begin
  SetLength(FensterInfo, 0);
  EnumWindows(@EnumWindowsProc, 0);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i: integer;
begin
  Form1.ListBox1.Items.Clear;
  for i:=0 to High(FensterInfo) do
  begin
    Form1.ListBox1.Items.Add(FensterInfo[i].Caption)
  end;
end;


@Tastaro: An dem Einspeichern liegt das nicht (dein Quelltext ergibt nach Def. genau das gleiche, denn Low(...) ist bei dynamischen Arrays immer 0). Und wenn ich mir die Ergebnisse in der Zeile der for-Schleife auswerten lasse (Arrayname markieren + Strg+F7) gibt er ja genau das richtige aus, er hat also irgendein Problem, welches der Debugger scheinbar nicht hat :(.
NeoInDerMATRIX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 245

Win95, Win98(+se), WinNT, Win2000, WinME, WinXP(+pro), VISTA, Linux(SuSe), DOS [MultiMon(3)], Vista
D6 PeE + (FP 2.0l) + D3 Pe + D2005+ D2006 Arch
BeitragVerfasst: Di 07.02.06 23:09 
Hi,

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:
Function EnumWindowsProc(Wnd: HWND): BOOL; StdCall;   
Var   
  Capt: Array [0..128of Char;   
Begin   
  Result:=true;   
  If IsWindowVisible(Wnd) and   
     ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0or   
      (HWND(GetWindowLong(Wnd, GWL_HWNDPARENT))=GetDesktopWindow)) and  
     ((GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW)=0)   
  then   
  begin  
    SendMessage(Wnd, WM_GETTEXT, Sizeof(Capt), integer(@Capt));  
    SetLength(FensterInfo, length(FensterInfo)+1);  
    inc(lengthvar);  
    FensterInfo[High(FensterInfo)].Caption:=Capt;  
    FensterInfo[High(FensterInfo)].Handle:=Wnd;  
  end;  
end;   
   
procedure TForm1.Button2Click(Sender: TObject);  
Begin
 BuildArray();
End;

Procedure tForm1.BuildArray();
Var
 I: Integer;
Begin
 EnumWindows(@EnumWindowsProc, 0);
 With Form1.ListBox1.Items do
  Begin
   Clear;
   For I:=0 to Length(FensterInfo) - 1 do
    Begin
     Add(FensterInfo[I].Caption);
    End;
  End;
End;


So sollte das eigentlich gehen. Du solltest die anzahl der Items mit Length - 1 abfragen. Nicht über HIGH etc.
Ist eindeutiger.

Cu
Neo