Fensterklasse mit Get-/SetWindowLong: Zugriff innerhalb der WndProc?
-
Hi,
ich verwende eine Klasse, die mit Hilfe von Get- bzw. SetWindowLong() die statische WndProc auf eine nichtstatische weiterleitet. Nun habe ich versucht aus der nichtstatische WndProc auf meine Member zuzgreifen, aber der Debugger findet kein this.
Ist das grundsätzlich so?
Grüße,
don_basto.
-
Hi,
don_basto schrieb:
Nun habe ich versucht aus der nichtstatische WndProc auf meine Member zuzgreifen, aber der Debugger findet kein this.
Das sieht konkret wie aus (GetWindowLong(Ptr) ?) ? ... Zeig mal den Codeabschnitt .
-
Statische Funktionen verfügen grundsätzlich über keinen This-Zeiger. Stell sie dir so vor, als dass sie wie Stand-Alone-Funktionen sind, also nicht in einer Klasse, die aber auf die protected- und private- Membervariablen zugreifen können.
Du kannst das so lösen, dass du in deinem Fenster irgendwo einen Pointerauf die Klasse (praktisch den this-Zeiger) speicherst. Entweder per SetWindowLong mit GWL_USER oder SetProp.
-
Badestrand schrieb:
Statische Funktionen verfügen grundsätzlich über keinen This-Zeiger. Stell sie dir so vor, als dass sie wie Stand-Alone-Funktionen sind, also nicht in einer Klasse, die aber auf die protected- und private- Membervariablen zugreifen können.
Du kannst das so lösen, dass du in deinem Fenster irgendwo einen Pointerauf die Klasse (praktisch den this-Zeiger) speicherst. Entweder per SetWindowLong mit GWL_USER oder SetProp.
Das stimmt zwar, aber ich glaube das meinte er nicht:
don_basto schrieb:
[...]Nun habe ich versucht aus der nichtstatische WndProc auf meine Member zuzgreifen, aber der Debugger findet kein this. [...]
EDIT: Oder hab ich was übersehen, doch nicht oder
-
Hier der Kode:
LRESULT CALLBACK Window::staticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { Window* wnd = (Window*)GetWindowLong(hWnd, GWL_USERDATA); switch(uMsg) { case WM_CREATE: wnd = (Window*)((CREATESTRUCT*)lParam)->lpCreateParams; SetWindowLong(hWnd, GWL_USERDATA, long(wnd)); } return wnd->wndProc(hWnd,uMsg,wParam,lParam); } LRESULT CALLBACK Window::wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_SYSCOMMAND: switch (wParam) { case SC_SCREENSAVE: case SC_MONITORPOWER: return 0; } break; case WM_KEYDOWN: // Fenster schließen if (wParam==VK_ESCAPE) _exit = true; // Ausnahme ! break; case WM_CLOSE: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,uMsg,wParam,lParam); }
Der Debugger meldet eine Ausnahme, wenn auf _exit (ein Member) zugegriffen wird. Der this-Zeiger ist Null.
-
WM_CREATE ist nicht die erste Nachricht die ein Fenster erhält.
Somit geht
return wnd->wndProc(hWnd,uMsg,wParam,lParam);
schief
-
Ich würde das:
wnd = (Window*)((CREATESTRUCT*)lParam)->lpCreateParams; SetWindowLong(hWnd, GWL_USERDATA, long(wnd));
mal direkt nach dem Erstellen, also nach deinem Aufruf von CreateWindow(Ex) machen; also in etwa so:
_hWnd = CreateWindowEx(...); SetWindowLongPtr(_hWnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(this));
-
Der Fehler liegt nicht an der Reihenfolge. Er tritt auch auf, wenn WM_CREATE vorher ausgelöst wurde.
//EDIT:
Der Aufruf von der von der statischen zur nicht-statische klappt immer, auch wenn WM_CREATE vorher nicht aufgerufen wurde. Nur ist das this der nicht-statischen Methode immer NULL.
-
Das Problem liegt beim Speichern des Zeigers:
Window* wnd = (Window*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
wnd ist danach 0.
//EDIT:
Ich hab den Fehler gefunden. Ich Idiot hatte vergessen, den this-Zeiger in CreateWindow() zu übergeben. Danke für Eure Mühe!Grüße,
don_basto.
-
if(wnd) { return wnd->wndProc(hWnd,uMsg,wParam,lParam); } else { return DefWindowProc(hWnd,uMsg,wParam,lParam); }
-
don_basto schrieb:
Das Problem liegt beim Speichern des Zeigers:
Window* wnd = (Window*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
wnd ist danach 0.
Wie sieht dein CreateWindow Aufruf aus?
-
Das war's.
Hab's auch gerade rausgefunden... .
-
don_basto schrieb:
Das war's.
Hab's auch gerade rausgefunden... .Huh?!, was wars denn jetzt ? Du hast doch vorher schon geschrieben, dass dein Problem gelößt sei... *iritiert sei*
-
CodeFinder schrieb:
don_basto schrieb:
Das war's.
Hab's auch gerade rausgefunden... .Huh?!, was wars denn jetzt ? Du hast doch vorher schon geschrieben, dass dein Problem gelößt sei... *iritiert sei*
Jo, Problem scheint gelöst zu sein, hat wohl vergessen bei CreateWindow this als Param zu parsen^^ Das hat der Poster mit den 11 Fragezeichen wohl übersehen
-
Ich hat den This-Zeiger bei CreateWindow() nicht mitgegeben. Nachdem ich den Fehler gefunden hatte und dann hier meinen alten Beitrag editiert, kam der ????-Beitrag zum CreateWindow().
-
Wegen mir aus hättest du auch nen Doppel-Post machen können, dann sieht man immerhin, dass du noch was geschrieben hast Sonst übersieht man sowas so leicht^^
-
Ahso, ok ok, so hatte ich's auch verstanden; war nur iritiert wg. dem Post von '???????????' .
-
Das "if(!wnd) dann DefaultWndProc" solltest du auf jeden Fall drinnen haben, sonst wird u.U. erst wieder 0 als this verwendet, nämlich bevor die WM_CREATE gekommen ist. Was zwar normal funktioniert solange man nicht über "this" zugreift (siehe GetSafeHwnd - *würg*), aber zumindest gefährlich ist (z.B. wenn man mal den Code ändert), und ich denke (bin aber nicht sicher) dass es auch laut C++ Std. nicht OK ist.
-
hustbaer schrieb:
Das "if(!wnd) dann DefaultWndProc" solltest du auf jeden Fall drinnen haben, sonst wird u.U. erst wieder 0 als this verwendet, nämlich bevor die WM_CREATE gekommen ist.
Jo das seh ich auch so .
hustbaer schrieb:
aber zumindest gefährlich ist (z.B. wenn man mal den Code ändert),
Was sollte man denn am Code ändern, so dass es 'gefährlich' wird ? ( konkret ? )
hustbaer schrieb:
und ich denke (bin aber nicht sicher) dass es auch laut C++ Std. nicht OK ist.
Was soll nicht dem C++-Standard entsprechen ?
-
CodeFinder schrieb:
hustbaer schrieb:
und ich denke (bin aber nicht sicher) dass es auch laut C++ Std. nicht OK ist.
Was soll nicht dem C++-Standard entsprechen ?
Afaik gehört es in den Bereich "undefiniertes Verhalten", wenn du eine Klassenmethode über den NULL-Zeiger aufrufen willst.
-
CStoll schrieb:
CodeFinder schrieb:
hustbaer schrieb:
und ich denke (bin aber nicht sicher) dass es auch laut C++ Std. nicht OK ist.
Was soll nicht dem C++-Standard entsprechen ?
Afaik gehört es in den Bereich "undefiniertes Verhalten", wenn du eine Klassenmethode über den NULL-Zeiger aufrufen willst.
ACh das meinte er damit, ja klar, das wird krachen .