Autor |
Beitrag |
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: 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)  .
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 public 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..128] of Char; begin Result:=true; if IsWindowVisible(Wnd) and ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0) or (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:
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 public 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..128] of Char; begin Result:=true; if IsWindowVisible(Wnd) and ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0) or (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
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: 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
      
Beiträge: 414
Erhaltene Danke: 23
|
Verfasst: 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
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 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: 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):
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..128] of Char; begin Result:=true; if IsWindowVisible(Wnd) and ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0) or (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:
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
      
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
|
Verfasst: Di 07.02.06 23:09
Hi,
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..128] of Char; Begin Result:=true; If IsWindowVisible(Wnd) and ((GetWindowLong(Wnd, GWL_HWNDPARENT)=0) or (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
|
|
|