Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 05:22

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 3 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: WinAPI und Function in Klasse
BeitragVerfasst: Sa Mär 27, 2004 22:41 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Okt 26, 2002 17:14
Beiträge: 188
Wohnort: Hannover/Lüneburg
Hallo!

Ich schreibe gerade meinen Basecode neu auf Basis einer ebsseren Objekt-Orientierten Struktur. Dabei benutze ich weiterhin nicht die VCL, sondern die reine WinAPI bzw. Xlib unter Linux. Nun habe ich das "Problem", dass ich für ein Fenster ja eine Function zur Message-Behandlung brauche:
Code:
  1. function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
Diese würde ich aber gerne in meine Klasse integrieren, also etwa TFensterklasse.WndProc... Dabei stellt sich das Problem, dass diese dann zwar aufgerufen wird, aber nur 3x mit dem Wert 0 für Msg und das Fenster nicht erstellt werden kann. Ich musste das ganze so lösen, damit er überhaupt erstmal compilierte:
Code:
  1. type
  2.   TWndProc = function (hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT of object; stdcall;
  3.  
  4. ...
  5.  
  6.   TFenster = class(TComponent)
  7.   private
  8.     FWndProc : TWndProc;
  9.     ...
  10.   public
  11.     function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  12.   end;
  13.  
  14. ...
  15.  
  16. procedure TFenster.Initialize;
  17.   ...
  18.   FWndProc := WndProc;
  19.   with FwndClass do begin
  20.     ...
  21.     lpfnWndProc   := @FWndProc;
  22.     ...
  23.   end;
  24.   ...
  25. end;
  26.  
  27. ...
  28.  
  29. function TFenster.WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  30. ...

Gibt es eine Möglichkeit, das innerhalb einer Klasse zu lösen, oder muss ich den etwas uneleganteren Weg gehen, die Function außerhalb der Klasse zu definieren und aus ihr eine Funktion innerhalb der Klasse aufzurufen?

_________________
Thunderman
Bei schwierigen Problemen entscheiden wir uns einfach für die richtige Lösung. Klar?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Mär 28, 2004 00:05 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Methoden haben noch den impliziten Self Parameter und deshalb besteht ein Zeiger auf eine Methode (procedure of object) auch aus der Objektreferenz und dem Zeiger auf die Methode. Daher kann diese Methode nicht direkt wie eine normale Funktion aufgerufen werden.

Die Funktion MakeObjectInstance aus der Unit Forms erzeugt für eine Methode einen kurzen Code Block, der zusätzlich noch den Self Parameter auf den Stack legt:

function MakeObjectInstance(Method: TWndMethod): Pointer;

Mit FreeObjectInstance gibt man das wieder frei.

procedure FreeObjectInstance(ObjectInstance: Pointer);

Das kann man aber auch auf ähnliche Art und Weise selber machen.
Dazu fügt man folgenden Assembler Code ein:

Code:
  1. pop edx;
  2. push Objectreferenz;
  3. mov eax,Sprungaddresse;
  4. push edx;
  5. jmp eax;


EAX und EDX können bei stdcall Aufrufen sowieso verändert werden. Daher ist das kein Problem. Das ganze speichert man am besten in einem Record:

Code:
  1.  PJMPFunc=^TJMPFunc;
  2.  TJMPFunc=packed record
  3.   popedx:byte;
  4.   push:byte;
  5.   obj:TObject;
  6.   mov:byte;
  7.   target:pointer;
  8.   pushedx:byte;
  9.   jmp:word;
  10.  end;
  11.  
  12. function MakeObjectInstance(m:TMethod):Pointer;
  13. var
  14.  func:PJMPFunc;
  15.  obj:TObject;
  16.  p:pointer;
  17. begin
  18. obj:=m.data;
  19. p:=m.code;
  20. func:=VirtualAlloc(nil,sizeof(TJMPFunc),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  21. func.popedx:=$5A;
  22. func.push:=$68;
  23. func.obj:=obj;
  24. func.mov:=$B8;
  25. func.target:=p
  26. func.pushedx:=$52;
  27. func.jmp:=$E0FF;
  28. result:=func;
  29. end;
  30.  
  31. procedure FreeObjectInstance(p:pointer);
  32. begin
  33. VirtualFree(p,0,MEM_RELEASE);
  34. end;
  35.  


Man muß hierbei VirtualAlloc benutzen weil bei Speicher, der mit GetMem belegt wird, das Execute Bit nicht gesetzt wird und das sonst bei neueren Prozessoren Probleme bereiten würde.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Mär 28, 2004 00:30 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Okt 26, 2002 17:14
Beiträge: 188
Wohnort: Hannover/Lüneburg
Danke, funktioniert einwandfrei.

_________________
Thunderman
Bei schwierigen Problemen entscheiden wir uns einfach für die richtige Lösung. Klar?


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 3 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 14 Queries | GZIP : On ]