封装WndProc问题

时间:2009-11-19 03:52:47

标签: c++ winapi

好的,所以我写了一个基本类来封装win32窗口。我最终创建了一个静态路由器回调函数来将消息路由到该类的另一个函数。

编辑好了我明白了

m_MainWindowHandle = CreateWindowEx(
    windowFormat, 
    L"LUDO ENGINE", 
    m_WindowName.c_str(), 
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    0,
    m_WindowDimensions.first,
    m_WindowDimensions.second,
    NULL, 
    NULL,
    m_EngineInstance,
    (void*)this);

我忘了传入(void *)这个指针。 AJKFHDJKDF

LRESULT CALLBACK Test::EngineBase::WndRouter(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{


    Test::EngineBase *base = NULL;

    if(message == WM_NCCREATE)
    {
        base = reinterpret_cast<Test::EngineBase*>((LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
        SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)base);
    }
    else
    {
        base = reinterpret_cast<Test::EngineBase*>(GetWindowLongPtr(hWnd, GWL_USERDATA));
    }

    if(base == NULL)
    {
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    base->SetHWnd(hWnd);
    return base->WndProc(hWnd, message, wParam, lParam);
}

调用此功能:

LRESULT CALLBACK Test::EngineBase::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;

    switch (message)
    {
    case WM_KEYDOWN:
        m_InputManager->GetKeyboard()->SetKeyPressed(static_cast<int>(wParam));
        break;
    case WM_KEYUP:
        m_InputManager->GetKeyboard()->SetKeyUnpressed(static_cast<int>(wParam));
        break;
    case WM_MOUSEMOVE:
    case WM_NCMOUSEMOVE:
        m_InputManager->GetMouse()->SetMouseMouse(LOWORD(lParam),HIWORD(lParam));
        break;
    case WM_MOUSEWHEEL:
        break;
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
            //case IDM_ABOUT:
            //    //DialogBox(m_EngineInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            //    //break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

然后我从EngineBase继承。现在WndRouter总是被调用,而不是总是导致base == NULL,所以它实际上从不调用WndProc函数。

我做错了什么?

修改

这是我如何将初始消息传入引擎:

while (returnValue == 9999)
{
    engine->Update();
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {                
            returnValue = static_cast<int>(msg.wParam);
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

}

Heres标题:

namespace Test
{   
    //forward defines
    namespace Input
    {
        class InputManager;
    }


    // main classs
    class EngineBase
    {
    protected:
        virtual HRESULT SetKeyBindings();
        virtual HRESULT LoadResources();

        static LRESULT CALLBACK WndRouter(HWND hWnd,  UINT message,  WPARAM wParam,  LPARAM lParam);
        virtual LRESULT CALLBACK WndProc(HWND hWnd,  UINT message,  WPARAM wParam,  LPARAM lParam);

        // Use reference counting schematics to prevent deletion.
        boost::shared_ptr<Test::Input::InputManager> m_InputManager;
    public:
        EngineBase(__in const HINSTANCE engineHandleInstance);
        ~EngineBase();

        // Engine Specific things
        HRESULT InitializeEngine(__in const int nCmdShow, __in const std::pair<INT, INT>& windowDimensions, __in const Test::String& windowName);
        HRESULT Register(__in const WNDCLASSEX& windowDefs);

        // Game Specific things
        virtual HRESULT Initialize() = 0;
        virtual HRESULT Update();

        inline void SetHWnd(__in const HWND windowHandle)
        {
            m_MainWindowHandle = windowHandle;
        }

        inline const std::pair<INT, INT> GetWindowDimensions()
        {
            return m_WindowDimensions;
        }

    private:
        HRESULT InitializeSubSystems();

        // Win32 stuff
        HRESULT CheckForOtherInstance();
        WORD    RegisterEngineClass();
        WNDCLASSEX  m_WindowClass;
        HWND        m_MainWindowHandle;
        HINSTANCE   m_EngineInstance;
        HANDLE      m_Mutex;

        std::pair<INT, INT> m_WindowDimensions;
        Test::String m_WindowName;
    };
}

编辑这就是我设置windProc def

的方法

在main.cpp

WNDCLASSEX windowClass;
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = NULL;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(1));
windowClass.hIconSm = LoadIcon(NULL, MAKEINTRESOURCE(2));
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = L"ENGINE";

if(FAILED(engine->Register(windowClass)))
{
    return FAIL;
}

注册执行此操作:

HRESULT Test::EngineBase::Register(__in const WNDCLASSEX& windowDefs)
{
    HRESULT hr = S_OK;
    m_WindowClass = windowDefs;
    m_WindowClass.lpfnWndProc = WndRouter;
    m_WindowClass.hInstance = m_EngineInstance;

    if(!RegisterClassEx(&m_WindowClass))
    {
        hr = E_CANNOT_CREATE_WINDOW_CLASS;
        return hr;
    }
    return hr;
}

1 个答案:

答案 0 :(得分:1)

从EngineBase继承了什么?

如何让初始消息流入EngineBase的WndProc?

您是否使用GWL_WNDPROC调用SetWindowLong将窗口指向WndProc? (如果你这样做,你可能会错过一些初始消息)。或者窗口的WNDCLASS指向您的EngineBase :: WndProc?