c++ - 封装WndProc问题

标签 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*)this 指针。 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);
    }

}

这里是标题:

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;
}

Register 这样做:

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;
}

最佳答案

什么继承自 EngineBase?

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

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

关于c++ - 封装WndProc问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1760784/

相关文章:

c++ - C++ 中使用指针传递 Char

c++ - 使用 clang 更快地完成代码

c++ - 调用 handle 为 NULL 的 CloseHandle(handle) 是否安全

winapi - explorer.exe重启后如何恢复 "missing"通知图标?

c++ - 将窗口置于最前面的正确方法是什么

c++ - 正则表达式匹配每种类型的一个或多个字符?

c++ - 如何获取 QGraphicsScene 项目中 QPolygonF 项目的当前角度?

c++ - 如何使用 QUdpSocket 连接服务器和路由器后面的客户端?

c - 如何将整数转换为 LARGE_INTEGER

winapi - 如何防止我生成的进程生成子进程?