AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

WndProc in Klasse

Ein Thema von Chewie · begonnen am 16. Jul 2003 · letzter Beitrag vom 21. Feb 2004
Antwort Antwort
Seite 2 von 4     12 34   
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#11

Re: WndProc in Klasse

  Alt 16. Jul 2003, 23:59
Ok, es gibt viele Wege.

Man kann, wenn man erst NACH der Erzeugung eines Fensterhandles ein normales Subclassing durchführen will, per Properties zum Fensterhandle arbeiten. Unter Properties sind NICHT die aus der VCL bekannten gemein, sondern die per API mit SetProp() einem Fenster zugeordnet werden. Man alloziert einmal ein Globales Atom, also einen System-eindeutigen String der per Handle angesprochen wird. Über dieses Handle kann man nun einen DWord mit SetProp() einem Fensterhandle zuordnen. Sozusagen eine neue Eigenschaft einem Fensterhandle definieren. Dahinein kommt dann Self. Die Fensterprocedure ist für alle Fenster die diesen Weg nutzen gleich und liest nun mit GetProp() Self des Fensterhandles aus. Danach ruft sie Szum Self die Fenstermethode auf.
Dieser Weg setzt voraus das man erst NACH der Erzeugung des Fensterhandles dieses Subclassing durchführen kann.
D.h. mindestens die Messages wm_Create und wm_NCCreate und wm_NCCalcSize werden verschluckt.

Eine andere Methode würde einen Speicherbereich allozieren in dem individueller Code steht. Dieser Speicherbereich wäre sozusagen ein ausführbarer Caller-Stub. Ich nutzen diesen Weg z.b. über Stackbasierte, lokale Variablen um z.b. Methodbasierende Callbacks aufrufen zu können. D.h. eigentlich müsste diese Callback mit einer Standard API konforme Aufrufkonvention deklariert sein, z.b. stdcall.
So kann man z.b. EnumWindows() eine Callback übergeben die eigentlich eine Objectmethode aufruft. Ähnliches geht auch mit Fensterproceduren.

In deinem Falle könntest Du diesen Speicherbereich direkt als Record Member im Object definieren. Sowas wie

Delphi-Quellcode:

type
  TMyObject = class
  private
    FStub: packed record
      MOV_EAX_OpCode: Byte;
      Self: Pointer;
      JMP_OpCode: Byte;
      Offset: Integer;
    end;
  end;
@Self.FStub wäre dann die Fensterprocedure. In FStub.MOV_EAX_OpCode muß der OpCode für MOV EAX,Konstant rein. In FStub.JMP_OpCode muß der OpCode für JMP +-OFFSET Konstant rein. Also ein relativer Sprung.

Gruß Hagen
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#12

Re: WndProc in Klasse

  Alt 17. Jul 2003, 10:49
Ich glaube, ich kann noch eine weitere Methode anbieten:

Hinter jedem Fenster ist Platz für einen Zeiger, den du mit SetWindowLongPtr anhängen kannst. Bei der Erzeugung des Fenster hängst du hier einfach den this-Zeiger (oder wie heißt der noch unter Delphi? Ach ja, Self) an. Zusätzlich erzeugst du eine "globale" Fensterprozedur, die du auch bei der Erstellung des Fensters angibst. Diese macht nichts anderes, als mit GetWindowLongPtr den Self-Zeiger aus dem Fenster zu holen und dann die Klassenmethode, die die Nachricht bearbeiten soll, aufruft. Weiß nicht, wie das unter Delphi ist, aber in C++ kann man die globale Fensterprozedur einfach der Klasse zuordnen, indem man sie als static deklariert (ist für die Übersicht besser).

Pseudo-Code:
Code:
function CommonWndProc(...);
var pClass: TDeineKlasse;
begin
  pClass := TDeineKlasse(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  Result := pClass.WindowProc(...);
end;

function TDeineKlasse.MyCreateWindow(...);
var hWnd: THandle;
begin
  hWnd := CreateWindow(...);
  SetWindowLongPtr(hWnd, GWLP_USERDATA, Self);
end;
So in etwa. Hab' mir die Methode bei Microsoft abgeguckt und sie funktioniert ganz gut und ist auch relativ einfach. Musst halt in der Fensterklasse nur noch die CommonWndProc als Fensterprozedur angeben.
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#13

Re: WndProc in Klasse

  Alt 17. Jul 2003, 12:50
Hi OregonGhost,

die Methode mit den Fensterprops, arbeitet genau wie deine.
Mit dem Unterschied das GWL_USERDATA vielen Programmieren bekannt ist und z.b. von deren Tools wie Mousetreiber usw. schon genutzt werden könnte. Es ist also mit GWL_USRDATA nicht sicher das dieser Platz mehrfach verwendet wird und somit unser Self überschrieben wird.

Deshalb mein Vorschlag mit SetProp() und einem eindeutigen Atom.

Gruß Hagen
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#14

Re: WndProc in Klasse

  Alt 17. Jul 2003, 13:07
So meinst du das... Hatte nur ein paar Worte gelesen, dir mir im ersten Moment spanisch vorkamen ;c)

Wie dem auch sei, der Platz bei GWLP_USERDATA ist, wie der Name andeutet, für die (fensterbesitzende) Anwendung reserviert, und Treiber, die diesen Platz verwenden, sind daher nicht gut programmiert.
Zitat von Microsoft:
GWLP_USERDATA [...] This data is intended for use by the application that created the window. Its value is initially zero.
Davon abgesehen kann man den Platz hinter dem Fenster beim Erzeugen, ich glaube der Klasse, vergrößern. Deine Methode ist wahrscheinlich sicherer, da hast du recht, aber dafür einen Tick umständlicher ;c)

Jedenfalls, in meiner Anwendung hat sich kein Treiber da einzunisten ;c)
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
Chewie

Registriert seit: 10. Jun 2002
Ort: Deidesheim
2.886 Beiträge
 
Turbo Delphi für Win32
 
#15

Re: WndProc in Klasse

  Alt 17. Jul 2003, 18:40
Danke euch beiden, ich werde mir das mal zu Gemüte führen. Muss das erstmal verdauen...
Martin Leim
Egal wie dumm man selbst ist, es gibt immer andere, die noch dümmer sind
  Mit Zitat antworten Zitat
Chewie

Registriert seit: 10. Jun 2002
Ort: Deidesheim
2.886 Beiträge
 
Turbo Delphi für Win32
 
#16

Re: WndProc in Klasse

  Alt 18. Jul 2003, 12:00
OK, ich hab also hier drei Methoden zur Auswahl.
  • Zunächst die erste Möglichkeit von negaH. Der Propertylist von dem Control wird als Property ein Zeiger auf das Objekt angehängt. Um auf diesen Pointer zuzugreifen, brauch ich dann nur das Fensterhandle und den Bezeichner, entweder ein String oder, noch besser, ein globales Atom. Klingt einfach und logisch, der Nachteil ist, dass ich immer noch keine Methode habe, also auch keinen Zugriff auf private-Felder.
  • Dann die andere Möglichkeit von negaH, die ich ehrlich gesagt nicht verstehe...
  • Und OregenGhosts ist im Ergebnis der ersten identisch, nur mit dem Unterschied, dass der Zeiger an das Fenster selbbst angehängt wird, allerdings ist dort in der Regel nur Platz für ein Zeiger, und wenn der schon belegt ist, gibts Probleme.

So, ich hab mir das nochmal aufgeschrieben, ums zu verstehen. Da Methode1 nicht viel aufwändiger ist als Methode 3, aber sicherer, fällt Methode 3 weg. Aber negaH, könntest du mir bitte nochmal die zweite Methode erklären? Wäre sehr nett.
Martin Leim
Egal wie dumm man selbst ist, es gibt immer andere, die noch dümmer sind
  Mit Zitat antworten Zitat
Gast
(Gast)

n/a Beiträge
 
#17

Re: WndProc in Klasse

  Alt 18. Jul 2003, 15:54
Vielleicht versuche ich es nochmal.

Du kannst (musst aber nicht) ein Atom reservieren. Ein Atom ist ein 16bit-Wert (ungefaehr wie ein Handle). Statt des Atoms kannst du SetProp() und GetProp() auch direkt einen String (mit Namen der Property) uebergeben. Hagen schlug das nur vor um die Eindeutigkeit des Wertes auf dem System zu gewaehrleisten. Denn Atome sind systemweit eindeutig! Allerdings sind sie wie auch DDE ein Relikt aus den Zeiten von Win16 (werden aber selbst in XP noch von MS benutzt).

Wenn du XP mit Themes benutzt, wird JEDES Fenster eine Window-Property haben, die dem Theme-Manager irgendwas sagt. Naeheres habe ich noch nicht rausbekommen. Wenn du Lust hast, kannst du mit meinem EDA mal etwas rumprobieren. Es kann Window-Properties fremder Anwendungen auslesen.

Ein Nachteil von Window-Properties soll nicht verschwiegen werden: sie sind weit langsamer als zB SetWindowLong().

SetWindowLongPtr() ist im uebrigen an mehreren Stellen falsch dokumentiert und deklariert (zumindest bei Delphi 4).

Zitat:
The most typical use for atoms is in Dynamic Data Exchange (DDE) applications. In the DDE protocol, applications use global atoms to identify the applications exchanging data, the nature of the data being exchanged, and the actual data items being exchanged. For more information about DDE, see Atoms and Shared Memory Objects. For examples that show how to use atoms, see the following topics:
  • Initiating a Conversation
  • Retrieving an Item from the Server
  • Submitting an Item to the Server
  • Terminating a Data Link
@OregonGhost: nicht der Treiber, sondern eine Hook-DLL subclassed die Fenster und haengt Werte an. Dies geschieht um bestimmte Rad-Features auch auf Fenstern zu benutzen, welche eigentlich diese Nachrichten nicht verarbeiten.
  Mit Zitat antworten Zitat
Chewie

Registriert seit: 10. Jun 2002
Ort: Deidesheim
2.886 Beiträge
 
Turbo Delphi für Win32
 
#18

Re: WndProc in Klasse

  Alt 18. Jul 2003, 16:29
Dass man statt den Atomenn auch Strings nehmen kann, ist mir klar, steht ja im SDK bei SetProp() dabei.
Hab ich ja auch geschrieben:
Zitat:
Um auf diesen Pointer zuzugreifen, brauch ich dann nur das Fensterhandle und den Bezeichner, entweder ein String oder, noch besser, ein globales Atom.
Mein einziges Problem ist wie gesagt, dass ich die WndProc gerne als Methode haben würde. Aber so wie es aussieht, muss ich mich wohl davon verabschieden. Dürfte auch so gehen.
Martin Leim
Egal wie dumm man selbst ist, es gibt immer andere, die noch dümmer sind
  Mit Zitat antworten Zitat
Gast
(Gast)

n/a Beiträge
 
#19

Re: WndProc in Klasse

  Alt 18. Jul 2003, 16:35
Davon kannst du dich definitiv verabschieden. Callbacks als Methode einbinden ist IMMER so eine Sache. Die Mechanismen haste ja in deinem ersten Post selbst erlaeutert
  Mit Zitat antworten Zitat
Chewie

Registriert seit: 10. Jun 2002
Ort: Deidesheim
2.886 Beiträge
 
Turbo Delphi für Win32
 
#20

Re: WndProc in Klasse

  Alt 18. Jul 2003, 16:42
Zitat von Assarbad:
Davon kannst du dich definitiv verabschieden. Callbacks als Methode einbinden ist IMMER so eine Sache. Die Mechanismen haste ja in deinem ersten Post selbst erlaeutert
Stimmt. Na ja, ich hab gedacht, vielleicht ließe sich vor Aufruf der Methode der Self-Zeiger in den Stack pushen, die Methode dann als Funktion simulieren und innerhalb der Funktion dann den Self-Zeiger wieder von Stack holen. Oder so was in der Art. Aber was solls, ich habs jetzt über die Properties geregelt.
Martin Leim
Egal wie dumm man selbst ist, es gibt immer andere, die noch dümmer sind
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz