WINAPI Klasse, Vererbung Problem
-
Hi ich habe eine Haupt Klasse
class FRM_CLASS { public: FRM_CLASS(); ~FRM_CLASS(); bool Timer(){}; virtual bool Create(UINT uMsg, WPARAM wParam, LPARAM lParam){}; ... LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); static int WINAPI WindowsProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); ... } 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); } LRESULT CALLBACK FRM_CLASS::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: { Create(uMsg, wParam, lParam); } break; ... }und dann
class FRM_STARTER : FRM_CLASS { public: bool Create(UINT uMsg, WPARAM wParam, LPARAM lParam); private: HWND hEditName, hEditIP, hButtonStart, hButtonLevelMaker; HBITMAP hBitmapLogo; }; bool FRM_STARTER::Create(UINT uMsg, WPARAM wParam, LPARAM lParam) { hEditName = CreateWindow("EDIT", "", WS_VISIBLE|WS_CHILD|WS_BORDER, 230, 70, 150, 20, hWnd, 0, hInstance,0); hEditIP = CreateWindow("EDIT", "", WS_VISIBLE|WS_CHILD|WS_BORDER, 230, 100, 150, 20, hWnd, 0, hInstance,0); hButtonLevelMaker = CreateWindow("Button", "Level Maker", WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 230, 130, 100, 20, hWnd, NULL, hInstance, NULL); hButtonStart = CreateWindow("Button", "OK", WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 340, 130, 40, 20, hWnd, NULL, hInstance, NULL); hBitmapLogo=(HBITMAP) LoadImage (hInstance,"logo.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION); return true; }nun möchte ich das die Funktion Create in der Kind Klasse definiert wird aber in der Eltern Klasse aufgerufen wird
anscheinend funktionierts nicht weil ich die Funktionen in der Windows Prozedur LRESULT CALLBACK FRM_CLASS::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ausführen lassen will
kann man das irgendwie so hinbiegen das sie laufen?
P.S.: Hoffe mal ihr habt mich verstanden
P.P.S.: Achja hier die Fehlermeldung:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt p_daldria.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 0040153F. Lesen von Adresse 00000000'. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------(EAccessViolation ist die Exception-Klasse für Fehler, die durch ungültige Speicherzugriffe ausgelöst werden.)
Hoffe ihr könnt mir helfen.
-
Sorry, aber dieser Code ist so unleserlich... vielleicht könntest Du ihn so formatieren, daß neue Sachen in ner neuen Zeile anfangen oder so.
-
class FRM_CLASS { public: FRM_CLASS(); ~FRM_CLASS(); bool Timer(){}; virtual bool Create(UINT uMsg, WPARAM wParam, LPARAM lParam){}; ... LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); static int WINAPI WindowsProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); ... } 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); } LRESULT CALLBACK FRM_CLASS::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: { Create(uMsg, wParam, lParam); } break; ... }und dann
class FRM_STARTER : FRM_CLASS { public: bool Create(UINT uMsg, WPARAM wParam, LPARAM lParam); private: HWND hEditName; }; bool FRM_STARTER::Create(UINT uMsg, WPARAM wParam, LPARAM lParam) { hEditName = CreateWindow("EDIT", "", WS_VISIBLE|WS_CHILD|WS_BORDER, 230, 70, 150, 20, hWnd, 0, hInstance,0); return true; }Hoffe mal ist jetzt leserlich.
-
Mach einmal den Destruktor virtual.
Anstatt die Funktionen nur als virtual zu deklarieren und ihnen dann einen sinnlosen Rumpf zu geben, mache sie rein virtuell (virtual void foo () = 0)
Warum verwendest du private Vererbung? Bist du dir dessen bewusst?Stichwort "Lesen von Adresse 0":
Anscheinend versuchst du, irgendwo lesend auf einen Null Zeiger zuzugreifen.
Benutze deinen Debugger, um herauszufinden, wo und sag uns die Stelle.
Ein Minimalbeispiel:class base { public: virtual void create () = 0; void foo () { create(); } }; class derived : public base { public: void create () { cout << "derived::create\n"; } }; int main () { derived d; d.foo(); }funktioniert nämlich.
FRM_CLASS *wnd = (FRM_CLASS*)GetWindowLong(hWnd, GWL_USERDATA); return wnd->WndProc(hWnd, uMsg, wParam, lParam);Bist du dir sicher, das wnd nicht vielleicht auf 0 zeigt?
-
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); }also das ist auf jeden fall schonmal falsch. es gibt noch nachrichten vor WM_CREATE. und dann machst du immer ungültige aufrufe.
-
wParam hat einen NULL Wert
und die int WINAPI WndProc ist nur eine zwischen Funktion die weiter auf die eigentliche WndProc verweist.
wenn ich das mit public vererbe bekomme ich dann acuh die Eigenschaften aus dem protected Bereich?
-
Ich glaube Du kannst in WM_CREATE noch keine Child-Windows erzeugen.
WM_CREATE wird gesendet, während Du das CreateWindow() des Elternfensters aufrufst. Erst dessen Return Wert liefert Dir den hWnd des Elternfensters zurück, der für das CreateWindow() der Kind Fenster gebraucht wird.
-
ne das ist für ein Fenster
in der Hauptklasse will ich halt die ganzen Funktionen haben und in der Kindklasse will ich die definieren.
Nur das Problem ist die WndProc will halt nicht so wie ich will.
Bei einer normalen Funktionen würdes funktionieren nur nicht bei dieser WndProc
-
Ich mein das hier:
hEditName = CreateWindow(...
Da geht es schon um Kindfenster. Ich gebe zu, mein Argument war nicht so gut, weil WindowsProc ja den hWnd liefert. Allerdings hab ich selbst immer Schwierigkeiten gehabt, wenn ich versucht habe, Kindfenster zu diesem Zeitpunkt zu erzeugen.
Aber wenn Dein WndProc ohnehin noch nicht läuft, musst Du das natürlich zuerst richten.
- die Argumente von ".." hast Du berücksichtigt?
- Ich weiss nicht genau was "CALLBACK" alles macht, aber hast Du nicht den falschen W.-Prozess mit CALLBACK deklariert? Das WndProc wird doch "von Dir selber" aufgerufen und ist kein CALLBACK. (Ist WINAPI synonym mit CALLBACK?)Bei mir sehen die Deklarationen jedenfalls etwa so aus:
virtual LONG WindowProc( HWND, UINT, WPARAM, LPARAM );
static LONG CALLBACK RegisteredProc(HWND, UINT, WPARAM, LPARAM);
// der WindowProc müsste nicht unbedingt virtual sein, wenn Du das nicht
// willst.Und der Code etwa so:
const LONG MSG_NOT_HANDLED = -1; LONG CALLBACK VWindow::RegisteredProc(HWND hWnd, UINT msg, WPARAM wP, LPARAM lP) { VWindow* pWindow = 0; if ( msg == WM_NCCREATE) //oder WM_CREATE { //ASSERT(lP); pWindow = (VWindow*)((CREATESTRUCT*)lP)->lpCreateParams; pWindow->_hWnd = hWnd; SetWindowLong(hWnd,GWL_USERDATA, (LONG)pWindow); } else { pWindow = (VWindow*)GetWindowLong(hWnd, GWL_USERDATA); if(!pWindow) { return DefWindowProc(hWnd, msg, wP, lP); } } // hier habe ich jetzt zusätzlichen Code eingefügt, so dass nichtbehandelte // Messages an DefWindowProc weitergeleitet werden. LONG result = MSG_NOT_HANDLED; .... // andere Messages result = pWindow->WindowProc(....); if(result == MSG_NOT_HANDLED) result = DefWindowProc(hWnd, msg, wP, lP); return result; }
-
[C++ Fehler] frmClass.cpp(38): E2268 Aufruf der undefinierten Funktion 'ASSERT'
wo krieg ich die Funktiondefinition her?
-
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