Problem beim Setzen einer WNDPROC ( mit Klassen )



  • Hallo zusammen,
    ich versuche gerade mi Hilfe von Klassen ein paar Fenster zu managen, aber es gibt da ein Problem. Und zwar bekomme ich, wenn ich mit SetWindowLong die WndProc für das Fenster setzen will, immer diese Fehlermeldung:

    error: aggregate value used where an integer was expected
    

    Ich habe keine Ahnung, was mir MinGW damit sagen will.
    Und hier der Code dazu. Wäre echt super, wenn mir jemand weiterhelfen könnte.

    class CBase
    {
    	public:
    		HWND hwnd;
    
    		virtual LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
    
    };
    
    class CWindow : public CBase
    {
    	public:
    		LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
    		{
    			return DefWindowProc( hwnd, msg, wparam, lparam );
    		}
    
    };
    
    CBase* window = new CWindow;
    SetWindowLong( hwnd, GWL_WNDPROC, (LONG)window->WndProc );
    

  • Mod

    Du kannst keine nicht statische Memberfunktion in dieser Form als Callback verwenden.
    http://www.mpdvc.de/html.htm#Q18



  • Ah, dankeschön!

    Ich verstehe aber noch nicht ganz, wie ich das Problem jetzt lösen soll. Bei einer WndProc werden doch alle Parameter benötigt, also kann ich keinen so verwenden, wie es auf der Website beschrieben ist.

    Das Problem ist ja, dass ich in CWindow Daten speichern möchte, die ich abrufen kann, wenn das Fenster zum Beispiel bewegt wird. Dann wird das Window handle an die Callback-Funktion weitergegeben, aber ich bräuchte einen Zeiger auf die Instanz von CWindow, in der sich das HWND befindet.

    Geht das? Und wenn ja, wie?



  • ne möglichkeit wäre doch

    auserhalb der Classe in der header

    class CWindow : public CBase
    {
    void SetVar(int, int);
    };
    extern CWindow m_Window;

    in der cpp

    CWindow m_Window;
    
    LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
    
    LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
    {
           switch(msg)
           {
            case WM_.....:
               m_Window.SetVar(1, 1);
            break;
           }
           return DefWindowProc( hwnd, msg, wparam, lparam );
    }
    

    und starten tust du ja die Callbackprocedur entweder über CreateDialog oder bei CreateWindow(Ex) über RegisterClass.


  • Mod

    Dann musst Du entweder die Informationen in den Windows Daten mit speichern und kannst diese Info mit Set/GetWindowLong(Ptr) nutzen.
    Oder Du verwendest z.B. Set/GetProp



  • Hmm bin gerade nen kleines Projekt bei sourceforge.net dazu am erstellen, weil es dauert Anfänger fragen ... ist eigentlich ganz einfach ...
    Du legst eine statische WindowProc für deine Fensterklasse an. Dann reagierst du darauf, ob ein WM_NCCREATE kommt. Da kannst du die Extra-Daten, die du bei CreateWindowEx angeben kannst, auswerten. (WM_CREATE würde auch gehen ... ist unter umständen aber zu spät.) Dann packst du die Extra-Daten per SetWindowLongPtr als GWL_USERDATA. Jetzt kannst du dir immer die Extra-Daten innerhalb der statischen MessageProc per GetWindowLongPtr holen. Als Extra-Daten gibst du halt einfach einen this-Zeiger an! Und schon ist das Problem gelöst 😛
    =>

    LRESULT CALLBACK Window::__message_proc(::HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
    	{
    		Window* pWindow = Window::FromHandle(hWnd);
    #pragma warning(disable: 4311)
    		if (message == WM_NCCREATE)
    		{
    			pWindow = reinterpret_cast<Window*>(reinterpret_cast<::LPCREATESTRUCT>(lParam)->lpCreateParams);
    			SetWindowLongPtr(hWnd, GWL_USERDATA, reinterpret_cast<LONG>(pWindow));
    		}
    #pragma warning(default: 4311)
    		return (pWindow != NULL ? pWindow->_message_proc(hWnd, message, wParam, lParam) : ::DefWindowProc(hWnd, message, wParam, lParam));
    	}
    

    ...

    public:
    		operator ::HWND() const		{	return m_hWnd;	}
    #pragma warning(disable: 4312)
    		static Window* FromHandle(const ::HWND& hWnd) { return reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWL_USERDATA)); };
    #pragma warning(default: 4312)
    

    ... _message_proc ist dann die MessageProc (idealerweise virtual ...) in deiner Klasse die NICHT statisch ist.

    public:
    		virtual LRESULT			_message_proc(::HWND, UINT, WPARAM, LPARAM);
    
    	private:
    		static LRESULT CALLBACK	__message_proc(::HWND, UINT, WPARAM, LPARAM);
    
    	public:
    		const ::HWND&			get_handle() const						{ if (m_hWnd == NULL || ::IsWindow(m_hWnd) == FALSE) throw std::invalid_argument("window handle does not exist"); return m_hWnd; }
    

    ...
    oder du wartest halt bis ich das Projekt fertig hab (muss nurnoch die einzellnen Messages (LB_GETITEMDATA usw.) in Funktionen packen und das halt auch mit den entsprechenden Controls ... sonnst bin ich fertig 😛 Mit vollständiger Dokumentation ^^ Mir liegt das Wohl der Anfänger halt am Herzen 😛



  • Hey danke, (D)Evil! 🙂
    Ich wusste gar nicht, dass man Userdaten angeben kann. So werde ich es machen.
    Vielen, vielen Dank!

    PS: Wie wird das Projekt heißen?


Anmelden zum Antworten