WINAPI Klasse, Vererbung Problem
-
nimm die zeile raus. ist unwichtig im moment.
-
jetzt bricht er schon hier ab
pWindow->_hWnd = hWnd;
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt p_daldria.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 00401185. Schreiben von Adresse 00000004'. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------
-
hast du auch CreateWindowEx(............., this) gemacht?
-
".....[?]" scheint immer ne gute Antwort zu wissen. Geht Dein Code jetzt?
Ich wollte noch folgendes hinzufügen: Du wirst nur für einen kleinen Teil der eingehenden Messages eigenen Code schreiben. Diejenigen Messages, die Du nicht selber behandelst, musst Du daher an "das System" weiterleiten (z.B. damit die Grösse des Fensters verändert werden kann, ohne dass Du Dich selber darum kümmerst). Deshalb habe ich meinem letzten Beitrag editiert und noch etwas Code eingefügt, damit die unbehandelten Messages an DefWindowProc() weitergeleitet werden können.
Ich muss meine Behauptung etwas abschwächen: Ich weiss eigentlich nicht welche Defaultverarbeitung in ::DefaultWindowProc() stattfindet, und welche erst hinter dem "return result;" kommt. Aber Du kannst ja mal einfach sehen und testen, ob und wozu Du das ::DefaultWindowProc() brauchst. Meine Klasse wurde geschrieben um selbstdefinierte Windows aber auch API-Steuerelemente zu verwalten, und ich kann jetzt nicht mehr so einfach testen wozu ich was brauche.
NB _hWnd: bin kürzlich gerügt worden, weil ich Unterstriche vor den Namen von Klassen-Variablen benutze; ich werd das wohl weiterhin so machen, weil ich ohnehin schon verdorben bin, aber ich möchte nicht schuld sein, wenn Du Dir einen schlechten Stil angewöhnst. Also: m_hWnd ist sexy, _hWnd ist doof.
-
ich hab alle ChildWindows bei meiner Create Funktion rausgenommen von daher glaub ich nicht das es an CreateWindow(..) liegt.
Hab mal die Dateien online gestellt vielleicht könnt ihr euch die ja mal anschauen
http://www.Spyke-Online.de/frmClass.cpp <--- Eltern Klasse
http://www.Spyke-Online.de/frmStarter.cpp <--- Kind Klasse
-
achja pWindow hat den Wert NULL (bei mir im Quelltext wnd)
-
kann denn keiner helfen

-
Wenn ich das richtig sehe, willst du in deiner statische Fensterprozedur einen Zeiger auf die entsprechend Instanz kriegen und verwendest die User Data?
Weiß nicht, ob es daran liegen könnte. Nur verwende doch mal statt SetWindowLong() SetProp() und um die Instanz dann zu holen GetProp(), das ging bei mir immer perfekt, vielleicht liegt es ja daran.
Hoffe ich lag nicht total daneben,
Grüße
JensE
-
Habe nicht Deinen ganzen Code gelesen, geschweige denn verdaut -
aber es scheint Du hast das hier"hast du auch CreateWindowEx(............., this) gemacht?"
noch nicht umgesetzt.
Es geht hier nicht um die ChildWindows. Sondern um die Erstellung des Hauptfensters.
wnd = (FRM_CLASS*)((CREATESTRUCT*)lParam)->lpCreateParams;
Hier kannst Du den Pointer auf Dein Frame nur auslesen, wenn Du diesen Pointer vorher in CreateWindow(Ex) als "Creation Parameter", übergeben hast.
Von allein weiss die API nichts über Deine C++ Klasse.
-
könntest du mir vielleicht komplett Anweisung für CreateWindowEx geben
und an SetWindowLong kanns nicht liegen da er nicht bis hinkommt, er bricht vorher schon ab
-
Ich glaube die Parameter in CreateWindowEx() solltest Du schon selber einsetzen. Ich kenne Dein Programm ja auch nicht so gut. Für den letzten Parameter (LPVOID lpParam // pointer to window-creation data) jedenfalls musst Du
this
eintragen (zumindest solange der Aufruf innerhalb einer Klassenfunktion erfolgt).Deine CreateWindowEx() sieht sonst ja auch nicht schlecht aus, so weit ich sehen kann.
In meiner eigenen Window Klasse habe ich das CreateWindowEx in einer eigenen Funktion Create(). Du scheinst die ganze Fenster-Erstellung in den Konstruktor der FRM_CLASS unterbringen zu wollen. Ich weiss im Augenblick keinen Grund warum das nicht gehen soll, aber dass Du auch noch den Messageloop im Constructor hast, wird auf die Dauer wohl zu Problemen führen. Der Constructor der abgeleiteten Klasse wird dann erst aufgerufen, wenn das Programm praktisch schon zu Ende ist.
NB:
Bist Du sicher, dass Du hInstance initialisiert hast? Kann nichts finden.
-
Das Problem ist die "Windows Procedure"-Funktion:
int WINAPI FRM_CLASS::WindowsProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { if ( uMsg == WM_CREATE ) SetWindowLong( hWnd, GWL_USERDATA, lParam); FRM_CLASS *wnd = (FRM_CLASS*)GetWindowLong(hWnd, GWL_USERDATA); return wnd->WndProc(hWnd, uMsg, wParam, lParam); }Wenn du der CreateWindowEx-Funktion den this-Zeiger als lParam übergibst, erwartest du, dass die Funktion zu allererst eine WM_CREATE Nachricht an die WindowsProc-Funktion sendet. Es ist aber so, dass CreateWindowEx noch andere Nachrichten an die Procedure-Funktion sendet bevor es die WM_CREATE Nachricht versendet. Daher erhält der Zeiger "wnd" einige male den Wert NULL, weil SetWindowLong erst aufgerufen wird wenn die WM_CREATE Nachricht erhalten wird, und das passiert erst ein wenig später.
Lösung: Du nimmst eine Dummy-Procedure-Funktion her, die einfach nur DefWindowProc aufruft. Du gibst diese bereits im WNDCLASS struct an:
wc.lpfnWndProc = WndProc_DUMMY; // wird später ersetzt
Wenn die CreateWindowEx-Funktion zurückkehrt machst du folgendes:
CreateWindowEx(...); // hier brauchst du kein "this" angeben
SetWindowLong(hwnd, GWL_USERDATA, (LONG)this); //"this"-pointer speichern
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)FRM_CLASS::WindowsProc); //richtige procedure-funktion einstellenUnd so sollten die Funktionen aussehen:
LRESULT WndProc_DUMMY(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { return DefWindowProc(hWnd, 0, uMsg, wParam, lParam); } LRESULT WINAPI FRM_CLASS::WindowsProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { static FRM_CLASS *wnd = NULL; wnd = (FRM_CLASS*)GetWindowLong(hWnd, GWL_USERDATA); return wnd->WndProc(hWnd, uMsg, wParam, lParam); }