![]() |
Re: Unerlaubte Member-Variablen im Service?
Hier die Lösung:
(was lange währt wird endilch gut heisst es doch? ;-) )
Delphi-Quellcode:
// constructor
// constructor PhService.Create; var t: TMethod; begin t.Code := @PhService.serviceproc; t.Data := self; m_serviceProcInst := MakeProcInstance(t); // m_serviceProcInst ist ein normaler Pointer, der an die API übergeben wird end; // destructor // destructor PhService.Destroy; begin FreeProcInstance(m_serviceProcInst); // aufräumen inherited; end; |
Re: Unerlaubte Member-Variablen im Service?
@ Phoenix & Motzi
ich stand gerade vor dem gleichen Problem. Und diese Lösung funktioniert perfekt ! Es war gut Phoenix, dass Du die Lösung noch gepostet hast, hätte ich auf die Schnelle nicht herausgefunden. Dagegen ist diese Lösung regelrecht umständlich: ![]() |
Re: Unerlaubte Member-Variablen im Service?
Ich habe jetzt mal versucht das mit der API-Funktion EnumWindows umzusetzen:
Delphi-Quellcode:
Das scheint leider nicht ganz zu funktionieren, da ich nur ein Handle ausgegeben bekomme.
program Project2;
{$APPTYPE CONSOLE} uses Windows; type TEnumWindows = class(TObject) private EnumProcInst: Pointer; function MakeProcInstance(M: TMethod): Pointer; procedure FreeProcInstance(ProcInstance: Pointer); function EnumWindows(hWnd: THandle; lp: LPARAM): Boolean; stdcall; public constructor Create; destructor Destroy; override; end; { TEnumWindows } function TEnumWindows.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 TEnumWindows.FreeProcInstance(ProcInstance: Pointer); begin // free memory FreeMem(ProcInstance, 15); end; constructor TEnumWindows.Create; var Method: TMethod; begin Method.Code := @TEnumWindows.EnumWindows; Method.Data := Self; EnumProcInst := MakeProcInstance(Method); EnumWindows(Cardinal(EnumProcInst), 0); end; function TEnumWindows.EnumWindows(hWnd: THandle; lp: LPARAM): Boolean; stdcall; begin Writeln(hWnd); Result := True; end; destructor TEnumWindows.Destroy; begin FreeProcInstance(EnumProcInst); inherited; end; var EnumWnds: TEnumWindows; begin EnumWnds := TEnumWindows.Create; EnumWnds.Free; Readln; end. |
Re: Unerlaubte Member-Variablen im Service?
Im Moment machst Du ja noch nichts mit der Klasse als solches. Probier mal, die EnumWIndowsProc direkt zu übergeben und schau ob Du dann mehrfach aufgerufen wirst. Es könnte sein, dass der ASM-Block den Rückgabewert nicht wieder an Windows zurück durchreicht - was Du aber brauchst..
|
Re: Unerlaubte Member-Variablen im Service?
Ich rufe es doch im Konstruktor auf.
Zitat:
|
Re: Unerlaubte Member-Variablen im Service?
@Luckie: Warum so kompliziert? nutze doch den lParam um die ObjectInstanz zu übergeben wenn du den lparam sowieso nicht nutzt. Und selbst wenn du den lparam nutzten willst kannst du dort auch einen Pointer auf einen Record übergeben der deinen eigentlichen lparam enthält und zustäzlich die Instanz.
Variante wenn lParam nicht benötigt wird
Delphi-Quellcode:
Der Fehler bei dir lag daran das du im Create zwar "EnumWindows" aufrufst, aber da EnumWindows eine Methode deiner Klasse ist wird diese aufgerufen und nicht die EnumWindows-Funktion aus der Unit Windows
function GlobalEnumWindows(hWnd: THandle; lp: LPARAM): Boolean; stdcall;
begin TEnumWindows(lp).EnumWindows(hWnd, 0); end; constructor TEnumWindows.Create; begin Windows.EnumWindows(@GlobalEnumWindows, Cardinal(Self)); end; function TEnumWindows.EnumWindows(hWnd: THandle): Boolean; stdcall; begin Writeln(hWnd); Result := True; end; Anstelle von:
Delphi-Quellcode:
müsste es also mindestens so aussehen:
constructor TEnumWindows.Create;
var Method: TMethod; begin Method.Code := @TEnumWindows.EnumWindows; Method.Data := Self; EnumProcInst := MakeProcInstance(Method); EnumWindows(Cardinal(EnumProcInst), 0); end;
Delphi-Quellcode:
ansonsten wird wie bereits erwähnt deine Methode aufgerufen und der erste Parameter ist dann nicht ein Handle sondern "Cardinal(EnumProcInst)".
constructor TEnumWindows.Create;
var Method: TMethod; begin Method.Code := @TEnumWindows.EnumWindows; Method.Data := Self; EnumProcInst := MakeProcInstance(Method); windows.EnumWindows(EnumProcInst, 0); end; |
Re: Unerlaubte Member-Variablen im Service?
:wall: :wall: :wall:
Ich habe es jetzt so:
Delphi-Quellcode:
Aber irgendwas stimmt mit dem Speicher nicht. Entweder sind die Fenstertitel abgeschnitten oder es hängt noch Zeichensalat hinten dran. Aber die Routine hab eich schon tausendmal so geschrieben. Muss ich da noch was beachten, wenn die Callback eine Methode einer Klasse ist?
type
TEnumWindows = class(TObject) private EnumProcInst: Pointer; function MakeProcInstance(M: TMethod): Pointer; procedure FreeProcInstance(ProcInstance: Pointer); function EnumWindows(hWnd: THandle; lp: LPARAM): Boolean; stdcall; public constructor Create; destructor Destroy; override; end; { TEnumWindows } function TEnumWindows.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 TEnumWindows.FreeProcInstance(ProcInstance: Pointer); begin // free memory FreeMem(ProcInstance, 15); end; constructor TEnumWindows.Create; var Method: TMethod; begin Method.Code := @TEnumWindows.EnumWindows; Method.Data := Self; EnumProcInst := MakeProcInstance(Method); Windows.EnumWindows(EnumProcInst, 0); end; function TEnumWindows.EnumWindows(hWnd: THandle; lp: LPARAM): Boolean; stdcall; var Buffer: PChar; len: Integer; begin if IsWindow(hWnd) and IsWindowVisible(hWnd) then begin len := SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0); if len > 0 then begin Buffer := GetMemory(len + 1); try SendMessage(hWnd, WM_GETTEXT, len, Integer(Buffer)); Writeln(Buffer); finally FreeMemory(Buffer); end; end; end; Result := True; end; destructor TEnumWindows.Destroy; begin FreeProcInstance(EnumProcInst); inherited; end; |
Re: Unerlaubte Member-Variablen im Service?
mach mal aus
Delphi-Quellcode:
einfach
SendMessage(hWnd, WM_GETTEXT, len, Integer(Buffer));
Delphi-Quellcode:
ansonsten fehlt dir die abschließende #0
SendMessage(hWnd, WM_GETTEXT, len + 1, Integer(Buffer));
Oder initialisiere den speicher vorher mit #0 [Edit]Tippfehler beseitigt[/Edit] |
Re: Unerlaubte Member-Variablen im Service?
:wall: :wall: :wall:
Das ist heute nicht mein Tag. Ich gehe jetzt erstmal in eine Besprechung. Mal sehen, was ich da für einen Mist verzapfen kann. :? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:04 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