Хорошо, я написал базовый класс для инкапсуляции окна 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.
Что я делаю не так?
EDIT
Вот как я получаю начальные сообщения в движок:
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;
}
Регистрация делает это:
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;
}