Problem mit WindowProc + Aufruf zusätzlicher, WindowProc



  • Ich hab grade angefangen, eine Klasse fürs Erstellen von Fenstern unter Windows mit der WinAPI zu erstellen. Dazu wollte ich dann eine statische Klassenmethode nehmen, die als WndProc dient und eine externe Funktion per Konstruktor übergeben, die dann zusätzlich aufgerufen wird, damit außerhalb der Klasse auch auf Nachrichten reagiert werden kann. Hier mein Code:

    main.cpp:

    #include <windows.h>
    #include <iostream>
    
    #include "mxWindows.h"
    
    bool bClosed = false;
    HINSTANCE g_hInst = 0;
    
    void WindowProc(mxWindows *pWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        /* Mach irgendwas mit den Nachrichten... */
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        g_hInst = hInstance;
    
        mxWindows::registerClass(CS_HREDRAW | CS_VREDRAW, NULL, NULL, g_hInst, NULL, LoadCursor(NULL, IDC_ARROW), (HBRUSH)COLOR_WINDOW, NULL, "Klasse1", NULL);
    
        mxWindows m(WS_EX_OVERLAPPEDWINDOW, "Klasse1", "Testfenster", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, g_hInst, NULL, &WindowProc);
    
        m.show(iCmdShow);
    
        return 0;
    }
    

    mxWindows.cpp:

    #include "mxWindows.h"
    
    std::vector<WNDCLASSEX> mxWindows::lRegisteredClasses(false);
    std::vector<mxWindows **> mxWindows::lOpenWindows(false);
    
    mxWindows::mxWindows(DWORD dExStyle, LPCTSTR pcClassName, LPCTSTR pcWindowName, DWORD dStyle, int iX, int iY, int iWidth,int iHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID pvParam, CUSTOMWNDPROC pfCustomWndProc)
         : pfCustomWndProc(NULL)
    {
        this->pfCustomWndProc = pfCustomWndProc;
        this->create(dExStyle, pcClassName, pcWindowName, dStyle, iX, iY, iWidth, iHeight, hWndParent, hMenu, hInstance, pvParam);
    }
    
    HWND mxWindows::create(DWORD dExStyle, LPCTSTR pcClassName, LPCTSTR pcWindowName, DWORD dStyle, int iX, int iY, int iWidth, int iHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID pvParam)
    {
        this->hWnd = CreateWindowEx(dExStyle, pcClassName, pcWindowName, dStyle, iX, iY, iWidth, iHeight, hWndParent, hMenu, hInstance, pvParam);
    
        return this->hWnd;
    }
    
    LRESULT CALLBACK mxWindows::wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        unsigned int iOpenWindowsCount = mxWindows::lOpenWindows.size();
    
        mxWindows *pWindow = NULL;
    
        for (unsigned int i = 0; i < iOpenWindowsCount; i++)
        {
            if ((*mxWindows::lOpenWindows[i])->hWnd == hWnd)
            {
                pWindow = *mxWindows::lOpenWindows[i];
                break;
            }
        }
    
        LRESULT lr = DefWindowProc(hWnd, uMsg, wParam, lParam);
    
        if (pWindow->pfCustomWndProc != NULL)
        {
            //(pWindow->pfCustomWndProc)(pWindow, uMsg, wParam, lParam); // diese Zeile einkommentieren, dann geht es nicht mehr
        }
    
        return lr;
    }
    
    void mxWindows::show(int iCmdShow)
    {
        ShowWindow(this->hWnd, iCmdShow);
    
        MSG msg;
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    bool mxWindows::registerClass(UINT uStyle, int iClsExtra, int iWndExtra, HINSTANCE hInstance, HICON hIcon, HCURSOR hCursor, HBRUSH hbrBackground, LPCTSTR pcMenuName, LPCTSTR pcClassName, HICON hIconSmall)
    {
        unsigned int iClassCount = mxWindows::lRegisteredClasses.size();
    
        for (unsigned int i = 0; i < iClassCount; i++)
        {
            if (mxWindows::lRegisteredClasses[i].lpszClassName == pcClassName)
            {
                return false;
            }
        }
    
        WNDCLASSEX wce;
    
        wce.cbSize = sizeof(WNDCLASSEX);
        wce.style = uStyle;
        wce.lpfnWndProc = &mxWindows::wndProc;
        wce.cbClsExtra = iClsExtra;
        wce.cbWndExtra = iWndExtra;
        wce.hInstance = hInstance;
        wce.hIcon = hIcon;
        wce.hCursor = hCursor;
        wce.hbrBackground = hbrBackground;
        wce.lpszMenuName = pcMenuName;
        wce.lpszClassName = pcClassName;
        wce.hIconSm = hIconSmall;
    
        if (RegisterClassEx(&wce))
        {
            mxWindows::lRegisteredClasses.push_back(wce);
    
            return true;
        }
    
        return false;
    }
    

    und schließlich die mxWindows.h:

    #ifndef MX_WINDOWS_H
        #define MX_WINDOWS_H
    
        #include <windows.h>
        #include <vector>
    
        class mxWindows
        {
            typedef void (*CUSTOMWNDPROC)(mxWindows *pWindow, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
            private:
                HWND create
                (
                    DWORD dExStyle,
                    LPCTSTR pcClassName,
                    LPCTSTR pcWindowName,
                    DWORD dStyle,
                    int iX,
                    int iY,
                    int iWidth,
                    int iHeight,
                    HWND hWndParent,
                    HMENU hMenu,
                    HINSTANCE hInstance,
                    LPVOID pvParam
                );
    
                static std::vector<mxWindows **> lOpenWindows;
                HWND hWnd;
                CUSTOMWNDPROC pfCustomWndProc;
    
                static std::vector<WNDCLASSEX> lRegisteredClasses;
    
            public:
                mxWindows
                (
                    DWORD dExStyle,
                    LPCTSTR pcClassName,
                    LPCTSTR pcWindowName,
                    DWORD dStyle,
                    int iX,
                    int iY,
                    int iWidth,
                    int iHeight,
                    HWND hWndParent,
                    HMENU hMenu,
                    HINSTANCE hInstance,
                    LPVOID pvParam,
                    CUSTOMWNDPROC pfCustomWndProc
                );
    
                static LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
                static bool registerClass
                (
                    UINT uStyle,
                    int iClsExtra,
                    int iWndExtra,
                    HINSTANCE hInstance,
                    HICON hIcon,
                    HCURSOR hCursor,
                    HBRUSH hbrBackground,
                    LPCTSTR pcMenuName,
                    LPCTSTR pcClassName,
                    HICON hIconSmall
                );
    
                void show(int iCmdShow);
                HWND getHwnd() const { return this->hWnd; }
        };
    #endif
    

    In der mxWindows.cpp steht ein Kommentar (//(pWindow->pfCustomWndProc)(pWindow, uMsg, wParam, lParam); // diese Zeile einkommentieren, dann geht es nicht mehr), der eigentlich mein Problem schon beschreibt. Ihr solltet den Code einfach kopieren und kompilieren können, da keine Abhängigkeiten vorhanden sein sollten, die ich nicht mitkopiert hab.

    Ich wäre euch sehr verbunden, wenn ihr nur auf mein Problem eingehen würdet und nicht z. B. auf die Idee kommen würdet zu fragen wieso ich g_hInst global gemacht habe (oh welch' Sünde :D), es handelt sich echt um ein ganz neues Projekt, in dem bestimmt viele Schönheitsfehler sind.



  • Bei mir kommt an dieser Stelle eine Windows-Fehlermeldung.

    Nach Korrektur in

    if(pWindow != NULL)
    

    erscheint das Fenster wie gewollt.



  • Bei mir gehts so auch net. Hab Windows 7 64 Bit (Problem?)



  • Hab ich das übersehen, oder wird lOpenWindows überhaupt nicht gefüllt?
    In diesem Fall bleibt pWindow NULL und "pWindow->pfCustomWndProc != NULL" dürfte eine Exception werfen.



  • Nunja, es ist schon spät und ich will ins Bett. 😃

    Wie gesagt, bei mir geht es nach der kleinen Korrektur.

    iOpenWindowsCount dürfte, so wie ich es sehe, 0 liefern, da der Vector nirgends mit dem mxWindow-Typ gefüllt wird. Weiter unten ist somit der Zeiger immer noch NULL. Ich vermute, dass da die Ursache zu finden ist.

    Ich verwende WinXP 32 Bit 😃

    // Edit 3 Mins zu spät



  • Windows hatte mir keine Rückmeldung gegeben, der Debugger dann aber schon (wieso hatte ich die Idee net früher? Manchmal steh ich echt auf der Leitung :)). Danke für die Hilfe, jetz gehts (lag daran, dass irgendwas NULL war, wie schon vermutet. "Irgendwas", weil ichs grade net im Kopf hab und zu faul bin zu schauen :D).



  • SetWindowLong und GWL_WNDPROC sollte dir beim redirektionieren helfen.

    Grüßße


Anmelden zum Antworten