Fensterklasse mit Get-/SetWindowLong: Zugriff innerhalb der WndProc?
-
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 .
-
@CodeFinder: es kracht eben mit vielen Compilern nicht solange "this" in der Funktion nicht dereferenziert wird, also kein Zugriff auf non-static Member. Dazu darf die Funktion natürlich auch nicht virtual sein.
Und das meinte ich auf mit "gefährlich", also einen 0 "this" Pointer zu "übergeben" bloss weils gut geht. Wenn man dann später mal den Code ändert so dass für jede Message irgendwelche Member angegriffen werden... *boom*