![]() |
Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsProc
Hi,
ich habe folgenden Code:
Delphi-Quellcode:
Der Source ist gekürzt.
type
TWaechter = class(TObject) private { Private-Deklarationen } TZeitgeber : TTimer; function EnumWindowsProc(const hWindow : DWORD;const AdwDummy : DWORD) : Longbool; stdcall; procedure TZeitgeberOntimer(Sender : TObject); procedure kontrolle(text:pchar); public constructor create; destructor destroy; procedure einstellungen; procedure enabled (res : boolean); { Public-Deklarationen } end; var liste : array of String; implementation function TWaechter.EnumWindowsProc(const hWindow : DWORD;const AdwDummy : DWORD) : Longbool; stdcall; var pCaption : PChar; // Die Adresse eines Buffers, der den jeweiligen Fenstertitel aufnehmen soll dwSize : DWORD; // Bufferlänge begin Result := true; // TRUE = weitermachen // Nur sichtbare Fenster prüfen if not IsWindowVisible(hWindow) then exit; // Ermitteln, wie lang der Text des Fenstertitels ist dwSize := SendMessage(hWindow,WM_GETTEXTLENGTH,0,0); // Speicher für die auszulesende Caption reservieren + 1, wg. der terminierenden 0 pCaption := AllocMem(dwSize+1); try // Fenstertitel auslesen // da als zweiter Parameter ein lParam erwartet wird, aber eine Adresse zu // übergeben ist, findet hier eine Typumwandlung statt SendMessage(hWindow,WM_GETTEXT,dwSize+1,lParam(pCaption)); // Fenstertitel anzeigen // Hier kann dann auch die Prüfung stattfinden, ob das Handle des gesuchten Fensters // an diese Funktion übergeben wurde, um damit anzustellen, was auch immer // passieren soll. // War es das richtige, dann kann man Result auf FALSE setzen, um anzuzeigen, // das keine weiteren Fenster durchgegangen werden müssen if (pcaption^ <> '') then kontrolle(pcaption); finally // Speicher wieder freigeben FreeMem(pCaption,dwSize+1); end; end; procedure TWaechter.TZeitgeberOntimer(Sender : TObject); begin EnumWindows(@EnumWindowsProc, 0); end; procedure TWaechter.kontrolle(text:pchar); var i :integer; bo : boolean; begin //Weitere Verarbeitungen mit dem Namen des Fensters end; constructor TWaechter.create; begin TZeitgeber := TTimer.create(nil); with TZeitgeber do begin interval := 500; onTimer := TZeitgeberOnTimer; enabled := false; end; SetLength(liste, 0); end; destructor TWaechter.destroy; begin SetLength(liste, 0); end; procedure TWaechter.enabled(res: boolean); begin TZeitgeber.enabled := res; end; end. In der Methode TZeitgeberOnTimer meldet der Compiler, dass die Variable nicht definiert ist. Das Problem liegt wohl daran, dass ich eine Methode aufrufe, die innerhalb des Objektes liegt, das geht aber anscheinend so nicht. Wenn ich vor EnumwinodwsProc die Definition TWaechter entferne, meldet er beim Aufruf von kontrolle einen Fehler, der dann natürlich logisch ist, weil das dann wieder innerhalb des Objektes ist. Kann ich das irgendwie lösen? es sollte schon objektorientiert sein. Beste Grüße Ulrich |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Delphi-Quellcode:
Nimm das Teil aus der Klasse raus oder versuch es mal in dem du die Function als static declarierst
function EnumWindowsProc(const hWindow : DWORD;const AdwDummy : DWORD) : Longbool; stdcall;
|
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hi,
wenn ich die Funktion aus der Klasse entferne, dann habe ich Probleme, die Funktion Kontrolle auszurufen, die wiederum in der Klasse definiert ist. Hast du da eine Lösung? ich habe es noch probiert und hinter die Funktion static geschrieben (stdcall natürlich entfernt, macht er aber auch nicht. Beste Grüße Ulrich |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
In der DL heißt es nicht static, sondern class function.
|
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hi,
ich habe eben noch mal gesucht, weil Delphi mir static nicht als fett markiert hat, kam mir das etwas komisch vor und bin fündig geworden. Ich habe es jetzt mal als:
Delphi-Quellcode:
deklariert und nun kommt der Fehler nicht mehr. Dafür sagt mir der Compiler in der Zeile:
class function EnumWindowsProc(const hWindow : DWORD;const AdwDummy : DWORD) : Longbool; stdcall;
Delphi-Quellcode:
Diese Form des Methodenaufrufes ist nur für Klassenmethoden erlaubt.
if (pcaption^ <> '')
then kontrolle(pcaption); Beste Grüße Ulrich |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Zitat:
EnumWindowsProc als Methode in Objecten einzufügen ist möglich, aber über einen kleinen Umweg. schau Dir mal den Link an. ![]() (recht weit unten MakeprocInstance) so hab ichs gelöst. Wenn Du hier nochmal gucken willst. ![]() Wenn Du nicht klar kommst, dann meld Dich nochmal, dann such ich Dir mal die Lösung aus meinem Proggi raus. Muss aber erstmal weg, bis morgen :-) |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Delphi-Quellcode:
Ich hoffe ich habe nicht zu viel geändert.
type
TWaechter = class(TObject) private ... class function EnumWindowsProc(hWindow : DWORD; fWaechter : TWaechter) : Longbool; stdcall; // const macht nur sinn bei Datentypen größer 4 Byte ... end; var liste : array of String; implementation class function TWaechter.EnumWindowsProc(hWindow : DWORD; fWaechter : TWaechter) : Longbool; stdcall; var sCaption : String; dwSize : DWORD; begin Result := true; // TRUE = weitermachen if not IsWindowVisible(hWindow) then exit; dwSize := SendMessage(hWindow, WM_GETTEXTLENGTH, 0, 0); if dwSize > 0 then begin SetLength(sCaption, dwSize); // Lass das plus 1 weg SendMessage(hWindow, WM_GETTEXT, dwSize, Integer(PChar(sCaption))); end else sCaption := ''; fWaechter.kontrolle(sCaption); end; procedure TWaechter.TZeitgeberOntimer(Sender : TObject); begin EnumWindows(@EnumWindowsProc, Integer(Self)); end; procedure TWaechter.kontrolle(const sText : String); // hier ist const angebracht var i :integer; bo : boolean; begin //Weitere Verarbeitungen mit dem Namen des Fensters end; constructor TWaechter.create; begin TZeitgeber := TTimer.create(nil); with TZeitgeber do begin interval := 500; onTimer := TZeitgeberOnTimer; enabled := false; end; SetLength(liste, 0); end; destructor TWaechter.destroy; begin SetLength(liste, 0); end; procedure TWaechter.enabled(res: boolean); begin TZeitgeber.enabled := res; end; end. Vorsicht: ungetest |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Ups,
bin gerade mit den Programmiersprachen ein wenig durcheinander gekommen. Habe static durch class getauscht!!! Functioniert es?????? |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hi,
@Neolithos: Deine Lösungsvorschlag funktioniert nicht. Dein Nachtrag ändert an der Situation auch nichts, denn der Aufruf fwaechter.kontrolle macht keinen sinn, weil es fWaechter gar nicht gibt. Du bist wohl von einem Formular ausgegangen. Zu Test und ausprobierzwecken hatte ich da such und da geht es auch. Jetzt ist es bei mir halt so, dass ich erst ein Objekt erzeugen muss, damit das überhaupt aktiv wird. @stoxx: Ich habe die vorgesclagen Links angesehen und mir das mal vorgenommen. Also: Kompilieren macht er jetzt ohne Probleme. Nur: wenn das Programm läuft, kommt es zu einem Totalabsturz und ich muss den Rechner neustarten. Könntest Du bitte mal bei Gelegenheit Deinen Code posten? Ich schau morgen eh erst wieder ab 17 uhr rein. Beste Grüße und schon mal Danke für Eure Bemühungen Ulrich |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Äh, ich übergeb doch eine Instanz von deiner Klasse TWaechter an die Function EnumWindowsProc
Delphi-Quellcode:
class function TWaechter.EnumWindowsProc(hWindow : DWORD; fWaechter : TWaechter) : Longbool; stdcall;
Delphi-Quellcode:
Was soll daran nicht functionieren! Genauere Informationen bitte!
procedure TWaechter.TZeitgeberOntimer(Sender : TObject);
begin EnumWindows(@EnumWindowsProc, Integer(Self)); end; |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hi,
ich habe es mir angesehen. Ich sage nur: Wer lesen kann, ist klar im Vorteil. Sorry, da war ich zu schnell. Ich habe es übersehen, dass Du die Definition der Methode geändert hast. Dann kann es theoretisch laufen. Kompiliere ich nun das, meldet mir der Compiler: Variable erforderlich in der Zeile:
Delphi-Quellcode:
Beste Grüße
EnumWindows(@EnumWindowsProc, Integer(Self));
Ulrich |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Das ist schnell gelöst
Delphi-Quellcode:
EnumWindows(@TWaechter.EnumWindowsProc, Integer(Self));
|
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Nimm dein Enum WindowsProc aus der Klasse raus und mach es so:
Delphi-Quellcode:
Wenn du es in der Klasse drin hast, wird automatisch der unsichtbare Self-Parameter mitgeführt von Delphi und dann passt die Deklaration nicht mehr wie sie eiegntlich von Windows sein müsste.
type
PMyEnumParam = ^TMyEnumParam; TMyEnumParam = record lb: TListbox; end; function GetWindows(const hWnd: Longword; Param: PMyEnumParam): LongBool; stdcall; var Len: Longint; S: string; begin Result := True; if not (IsWindow(hWnd) and IsWindowVisible(hWnd)) then Exit; Len := SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0); if Len > 0 then begin SetLength(S, Len); SendMessage(hWnd, WM_GETTEXT, Len + 1, Longint(Pchar(S))); Param.lb.Items.Add(s); end; // mit Result = False kann die Callbackfunktion vorzeitig verlassen werden end; procedure TForm1.Button1Click(Sender: TObject); var Param: TMyEnumParam; begin Param.lb := Listbox1; EnumWindows(@GetWindows, LPARAM(@Param)); end; |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hi alle miteinander,
erstmal Danke für Eure Bemühungen. Ich habe dank Eurer Hilfe das Problem gelöst. Nun noch mal im Detail: @Neolithos: Ich habe es so gemacht, wie angegeben. Allerdings stürzt das Programm dann komplett ab. Irgendeine Zugriffsverletzung. Wo genau der Fehler ist, kann ich Dir nicht sagen. @Luckie: Ich habe jetzt Deine Methode ausprobiert und tatsächlich, das funktioniert. Noch mal, recht herzlichen Dank. Ihr seid eine richtig KLASSE Forum. Die Seite ist auch meine Startseite, weil Sie mir so gut gefällt. Ein dickes Lob an Euch. :thuimb: :bounce1: Ulrich |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Ich dachte bei class-Sachen gibt es keine Instanz.
Lieg ich da ein bißchen falsch. Wenn Ja! Dann:
Delphi-Quellcode:
Das mit der Struktur kann man sich sparen.
function WaechterEWProc(hWindow : DWORD; fWaechter : TWaechter) : Longbool;
... begin .. end; EnumWindows(@WaechterEWProc, Integer(Self)); |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hallo Ustra,
falls Du es doch noch schön objectorientiert machen möchtest, und somit auch auf alle Methoden des Objectes zugreifen kannst. Hier nochmal die Lösung viele Grüße stoxx
Code:
unit Unit2;
interface type Tmyclass = class; private enumpointer : Pointer; function EnumWinProc(WinHandle: HWND; lParam: LPARAM): boolean; StdCall; public constructor create; virtual; destructor destroy; override; procedure aufruf; end; // von Tmyclass implementation function MakeProcInstance(M: TMethod): Pointer; begin // allocate memory GetMem(Result, 15); asm // MOV ECX, MOV BYTE PTR [EAX], $B9 MOV ECX, M.Data MOV DWORD PTR [EAX+$1], ECX // POP EDX MOV BYTE PTR [EAX+$5], $5A // PUSH ECX MOV BYTE PTR [EAX+$6], $51 // PUSH EDX MOV BYTE PTR [EAX+$7], $52 // MOV ECX, MOV BYTE PTR [EAX+$8], $B9 MOV ECX, M.Code MOV DWORD PTR [EAX+$9], ECX // JMP ECX MOV BYTE PTR [EAX+$D], $FF MOV BYTE PTR [EAX+$E], $E1 end; end; ////////////////////////////////////////////////////////////////////////////////// procedure FreeProcInstance(ProcInstance: Pointer); begin // free memory FreeMem(ProcInstance, 15); end; ////////////////////////////////////////////////////////////////////////////////// constructor Tmyclass.create; var t : Tmethod; begin inherited create; t.Code := @Tmyclass.enumwinproc; t.Data := self; enumpointer := makeProcInstance(t); end; // von create ////////////////////////////////////////////////////////////////////////////////// destructor Tmyclass.destroy; begin FreeProcInstance(enumPointer); // aufräumen inherited destroy; end; /// von free ////////////////////////////////////////////////////////////////////////////////// function Tmyclass.EnumWinProc(WinHandle: HWND; lParam: LPARAM): boolean; StdCall; begin ... Code end; // von enumwindowsprocedure ////////////////////////////////////////////////////////////////////////////////// // Aufruf // procedure Tmyclass.aufruf; begin EnumWindows(enumpointer,0); end; end. |
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Zitat:
|
Re: Wo ist hier der (Denk-)Fehler? Aufruf von EnumWindowsPro
Hi,
@stoxx: ich habe es nicht mehr ausprobiert, aber ich denke, dass würde laufen. Luckies variante ist auch gut. Wenn ich das nächste Mal vor dem Problem stehe, werde ich noch mal Deine Lösung ausprobieren. Vielleicht mache ich das noch. Trotzdem danke für Deine Bemühungen. Beste Grüße Ulrich |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:35 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz