WndProc und Direct3D...



  • AAAAHHHHH
    langsam werde ich echt wahnsinnig. ich will seit tagen die "fensterklasse" meiner engine verbessern, doch wie gesagt, HÖLLE. es geht darum, dem user der engine die möglichkeit zu geben, seine eigene message proc zu schreiben. z.z. löse ich das so:
    ich habe eine funktion WndProc(HWND hWindow UINT uMessage, etc.(, eine "normale" message procedure also. der einzige befehl, den diese aufruft ist folgender:
    return g_Window->MessageHandler(hWindow, uMessage, wParam, lParam(;
    gWindow ist ein globaler zeiger auf ein objekt meiner fensterklasse. diesem wird im konstruktor von eben dieser der this zeiger zugeordnet, sodass die vom user definierte und von meiner fensterklasse abgeleitete Klasse in WndProc auch die vom user überladene messageHandler funktion aufruft. (in messagehandler werden natürlich die window messages behandelt). damit dies gelingt mus MessageHandler() ja eine virtual definierte funktion sein, hier gibt es jedoch probleme:
    sobald die funktion als virtua deklariert wird, scheitert die CreateDevice Methode von IDirect3D8. ich weiß nicht, woran das liegt und verzweifle langsam.
    Zur Info: die createdevice funktion wird von Initialize() in meiner Grafik-Klasse aufgerufen. diese klasse enthält einen pointer auf einén pointer auf ein objekt meiner fensterklasse.
    sorry für eventuelle rechtschreibfehler und danke schonmal für hoffentlich (bald ;-)) kommende Hilfe...
    *kurzvormweinen*



  • ich hab Dich ehrlich gesagt nicht genau verstanden, aber ich könnte mir vorstellen, daß der Fehler daran liegt daß du deine virtuelle Funtkion im Konstruktor der Basisklasse aufrufst, was Du nicht tun solltest! (Die Basisklasse weiß bei der Konstruktion noch gar nix von der vererbten Klasse und deren virtuellen Funktionen)



  • du könntest doch auch die WndProc per parameter an die funktion weitergeben, die WNDCLASS definiert. so mache ich es auf jedenfall.



  • der konstruktor weißt nur einem pointer auf die basis klasse den this-zeiger zu:

    // ACHTUNG, stark vereinfacht!
    class Window
    {
    public:
        Window();
        ~Window();
    };
    
    Window * g_Window = NULL;
    
    Window::Window()
    {
        g_Window = this;
    }
    

    ich versuche es nochmal zu erklären:

    Die WNdProc ist außerhalb der fensterklasse, deshalb, und wegen des virtuellen funktionen habe ich das "globale fenster". denn in wndproc wird oben bereits genannte zeile ausgeführt. MessageHandler ist die funktion, die eigentlich die messages bearbeitet, WndProc ist nur ein platzhalter, den ich an die WNDCLASSEX struktur übergebe. so kann der user der engone seine eigene funktion zum messages verarbeiten überladen. damit dieses funktioniert, muss sie virtual sein. g_Window->MessageHandler(...); führt sonst ja nur die standart message procedure aus.

    was mich am meisten verwirrt: was hat das mit direct3d zu tun (CreateDevice schlägt ja fehl).

    EDIT: @red2k das ginge natürlich, aber ich hätte eben gerne eine "built in" funktion. wenn es jedoch nicht anders geht, muss ich das wohl so machen, aber vielleicht fällt jemandem (oder sofgar mir... ;-)) noch was ein.



  • @red2k
    etwas peinlich, aber könntest du bitte mal ein beispiel posten...? ich übergebe an create (definiert in meiner fensterklasse) nun die funktion:
    LRESULT CALLBACK WndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam);
    in der deklaration steht:
    void Window::Create(...LRESULT (*) (HWND, UINT, WPARAM, LPARAM)...)
    Ich übergebe also so:
    Window CWindow;
    CWindow.Create(...WndProc...);

    ich bekomme dann einen fehler, und zwar, dass der compiler nicht von LRESULT (__cdecl*)(HWND, UINT, WPARAM, LPARAM) zu LRESULT (__stdcall*)(HWND, UINT, etc.) oder umgekehrt konvertieren kann. dann, wenn ich den übergebenen parameter dem entsprechenden WNDCLASSEX-Member zuweisen will, bekomme ich eine ähnliche ausgabe... aaahhh bitte ein beispiel 😞



  • einfach so:

    void Window::Create(WNDPROC wp)
    {
    //(...)
    wc.lpfnWndProc = wp;
    //(...)
    }
    


  • Ist WNDPROC denn definiert?? probiers gleich mal, danke schonmal



  • Babbo schrieb:

    Ist WNDPROC denn definiert?? probiers gleich mal, danke schonmal

    ja: typedef LRESULT (*WNDPROC)(HWND,UINT,WPARAM,LPARAM)



  • So, das programm startet jetzt, aber ich bekomme immer noch eine fehlermeldung, unhandled expressio oder so.
    CreateDevice liefert Invalid Call zurück, da das device dann nach der funktion immer noch NULL ist, ist die oben genannte fehlermeldung bei der nächsten funktion, die vom device aufgerufen wird, lgisch, ich verstehe aber nicht, warum CreateDevice berhaupt fehlschlägt... *heul*
    HIIILFEEE 😞 😞

    EDIT: Ich habe ein wenig rumprobiert: ich frage den Error-Code von CreateDevice normal mit FAILED ab und lasse ggf. eine fehlermeldung ausgeben. Daszu benutze ich Messagebox.

    // m_pIDirect3D ist (natürlich ;-)) ein Pointer auf ein IDirect3D9 Interface.
    if (FAILED(m_pIDirect3D->CreateDevice(...)
        // m_pWindow ist ein Pointer auf ein WindowObjekt in meiner Grafik Klasse.
        m_pWindow->MessageBox("Fehler", "CreateDevice");
    

    mir viel auf, das die messagebox garnicht angezeigt wurde. ich setztte deswegen einen breakpoint in diese zeile und der debuger stoppte das programm rechtmäßig. Merkwürdig, ich schaute mir den Rumpf meiner Window::MessageBox funktion an:

    int Window::MessageBox(char * Caption, char * Text)
    {
        return ::MessageBox(m_hWindow, Text, Caption /*oder andersrum...?*/, MB_OK | M_BICONERROR);
        m_hWindow ist ein Member der Window Klasse vom Typ HWND.
    }
    

    Wenn ich nun das m_hWindow durch NULL ersetze wird die Message normal angezeigt. ich schloss daraus, dass das m_hWindow "kaputt" sein muss und schaute mir die ausgabe des debuggers an, und tatsächlich, m_hWindow hatte den Wert 0xcccccccc, als ich auf das plus vor dem variablennamen klickte stand in der tabelle (ich meine die am unteren rans von ms vc++ 6):
    Unused | CXXoo3o Error, expression cannot be evaluatet (oder so)

    hoffe mit diesen infos kann mir wer helfen, danke nochmal schonmal 🙂



  • Ist deine Klasse ist nicht ordnungsgemäß instantiert?

    (Die dx debug runtimes sollten merken, wenn der hwnd ungültig ist.)

    Bye, TGGC (Der Held ist zurück)



  • hm, also, ich habe noch ein wenig rumprobiert, ich erstelle jetzt ein globales Objekt meiner abgeleiteten Klasse, anstatt in WunMain. irgendwie geht es jetzt... koisch.
    Danke an alle für die Hilfe, bis zum nächsten Mal 😉
    cya



  • #define globale Ende_aller_Probleme?

    Bye, TGGC (Der Held ist zurück)



  • Ja, ich weiß, globalen sind nicht gerade die beste lösung, aber in den dx samples wird das auch so oder so ähnlich gemacht...
    (d.h. natürlich NICHT, dass alles, was MS verzapft gut ist... ;-))
    cya


Anmelden zum Antworten