[gelöst] WndProc bei einer Fenster Klasse



  • Moin Moin zusammen!

    Mein aktuelles Ziel ist es eine Fenster Klasse zu schreiben von der ich später erben kann.
    Doch leider habe ich gerade etwas Stress mit der WndProc, denn ich möchte sie später nach Lust und Laune überschreiben können.
    Was ich bisher mache:

    UiWindow.h:

    #ifndef __UIWINDOW_H__
    #define __UIWINDOW_H__
    
    #include "UiWidget.h"
    
    #include <Windows.h>
    #include <string>
    
    class UiWindow : public UiWidget
    {
    public:
    	UiWindow(HINSTANCE _hInst, UiWidget* _parent = 00);
    	~UiWindow();
    
    	void Show();
    
    protected:
    	virtual LRESULT WndProc(HWND _hwnd, UINT _msg, WPARAM _wParam, LPARAM _lParam) = 0;
    
    private:
    	static LRESULT CALLBACK InternalWndProc(HWND _hwnd, UINT _msg, WPARAM _wParam, LPARAM _lParam);
    
    private:
    	std::wstring	m_appName;
    	std::wstring	m_windowName;
    	HINSTANCE		m_hInst;
    	HWND			m_windowHandle;
    };
    
    #endif //__UIWINDOW_H__
    

    UiWindow.cpp:

    #include "UiWindow.h"
    
    UiWindow::UiWindow(HINSTANCE _hInst, UiWidget* _parent)
    	: UiWidget(_parent)
    	, m_appName(L"AppName")
    	, m_windowName(L"UiWindow")
    	, m_hInst(_hInst)
    {
    	WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX);
    	wcex.style = CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc = InternalWndProc;
    	wcex.cbClsExtra = 0;
    	wcex.cbWndExtra = 0;
    	wcex.hInstance = m_hInst;
    	wcex.hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_APPLICATION));
    	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    	wcex.lpszMenuName = NULL;
    	wcex.lpszClassName = m_appName.c_str();
    	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
    
    	if(!RegisterClassEx(&wcex))
    	{
    		MessageBox(00, L"Can't register WNDCLASSEX!", L"Error", MB_OK | MB_ICONERROR);
    		return;
    	}
    
    	m_windowHandle = CreateWindow(
    		m_appName.c_str(),
    		m_windowName.c_str(),
    		WS_OVERLAPPED,
    		CW_USEDEFAULT,
    		CW_USEDEFAULT,
    		500,
    		100,
    		00,
    		00,
    		m_hInst,
    		00
    		);
    
    	if (!m_windowHandle)
    	{
    		MessageBox(00, L"Can't create window!", L"Error", MB_OK | MB_ICONERROR);
    		return;
    	}
    
    	SetWindowLong(m_windowHandle, GWLP_USERDATA, (long)this);
    
    	Show();
    
    	MSG msg;
    	while (GetMessage(&msg, 00, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    }
    
    UiWindow::~UiWindow()
    {
    
    }
    
    void UiWindow::Show()
    {
    	ShowWindow(m_windowHandle, SW_NORMAL);
    }
    
    LRESULT UiWindow::InternalWndProc(HWND _hwnd, UINT _msg, WPARAM _wParam, LPARAM _lParam)
    {
    	UiWindow* window = (UiWindow*)GetWindowLong(_hwnd, GWLP_USERDATA);
    
    	if (window == 00)
    	{
    		return DefWindowProc(_hwnd, _msg, _wParam, _lParam);
    	}
    
    	return window->WndProc(_hwnd, _msg, _wParam, _lParam);
    }
    

    WindowsEntryPoint.cpp:

    #include "UserInterface\UiWindow.h"
    
    class TestWindow : public UiWindow
    {
    public:
    	TestWindow(HINSTANCE _hInst, UiWindow* _parent = 00)
    		: UiWindow(_hInst)
    	{
    		Show();
    	}
    protected:
    	virtual LRESULT WndProc(HWND _hwnd, UINT _msg, WPARAM _wParam, LPARAM _lParam) override
    	{
    		return DefWindowProc(_hwnd, _msg, _wParam, _lParam);
    	}
    };
    
    int WINAPI WinMain(HINSTANCE _hInst, HINSTANCE _hPrevInst, LPSTR, int)
    {
    	int result = 0;
    
    	TestWindow window(_hInst);
    
    	return result;
    }
    

    Wenn ich das jetzt ausführe bekomme ich eine "Unhandled exceptio at xyz(ucrtbased.dll)..." Meldung.
    Auf der Suche nach einer Lösung oder anderen Art der Implementierung habe ich noch diese beiden Varianten ausprobiert:
    http://www.codeproject.com/Articles/2556/A-Simple-Win-Window-Wrapper-Class
    http://members.gamedev.net/sicrane/articles/WindowClass.html
    Bei beiden bekomme ich eine "Debug Error! abort() has been called!" Meldung.

    Sieht einer den Fehler oder kennt jemand eine andere Art der Implementierung die ich verwenden kann?
    Ich verwende im Moment Visual Studio 2015 und das Windows 8.1 SDK unter Windows 10 64x.
    Die UiWidget Klasse ist im Moment noch leer und beinhaltet neben dem Constructor und Destructor noch nichts.

    MfG BlackArma



  • Virtuelle Funktionen funktionieren im Konstruktor nicht! Da du in der Basisklasse für die Funktion UiWindow::WndProc keine Definition angibts, knallt es in der Nachrichtenschleife.

    Edit: Eine Frage habe ich aber: warum verwendest du für 0 die oktale Notation 00?



  • Biolunar schrieb:

    Virtuelle Funktionen funktionieren im Konstruktor nicht! Da du in der Basisklasse für die Funktion UiWindow::WndProc keine Definition angibts, knallt es in der Nachrichtenschleife.

    Okay, wusste ich nicht, wieder mal was gelernt.
    Aber selbst wenn ich eine Definition angebe wird nur die aus der Basisklasse aufgerufen und nicht die überschriebene, was mir eigentlich lieber wäre.
    Ich habe das alles jetzt einfach mal in eine eigene Funktion gepackt und nun geht es. Danke schon mal!

    Biolunar schrieb:

    Edit: Eine Frage habe ich aber: warum verwendest du für 0 die oktale Notation 00?

    Hat mir mal ein Dozent vor einer halben Ewigkeit gezeigt und ich habe irgendwie sofort gefallen daran gefunden, vermutlich weil ich ein wenig schreibfaul bin.
    Außerdem kann ich so immer noch erkennen ob es ein Pointer ist, wenn ich mal Code von mir eine Zeit lang nicht mehr angefast habe.



  • Dafür gibt es nullptr 😉
    Ein kleine Sache noch: Ich rate dir, windows.h und allgemein _riesige_ headerdateien nicht in andere header einzubinden, sondern nur im cpp-module. Solche dateinen treiben den compiliervorgang wahnsinnig in die Höhe, selbst wenn ein cpp-modul diese header überhaupt nicht braucht, ihn aber trotzdem indirekt includiert. Lösen kannst du es mit z.b. forwarddeklarationen einer struktur wo windows.h spezifisches zeug drin ist, welche dann im cpp-modul definiert ist und dynamisch erzeugt wird, jedenfalls so in der Art.
    Das sind jedenfalls meine Erfahrungen 😉


  • Mod

    roflo schrieb:

    Ein kleine Sache noch: Ich rate dir, windows.h und allgemein _riesige_ headerdateien nicht in andere header einzubinden, sondern nur im cpp-module. Solche dateinen treiben den compiliervorgang wahnsinnig in die Höhe, selbst wenn ein cpp-modul diese header überhaupt nicht braucht, ihn aber trotzdem indirekt includiert.

    Hier sollte man einfach Precompiled Header einsetzen. Dann kostet das auch keine Zeit, oder entsprechend viel weniger.


Log in to reply