Another downer was the fact that XInput for C++ looks almost exactly like DirectInput, except for the fact that it innately supports the 360 controller (or is designed around it or whatever.) It's largely function based, which is lame IMHO; I guess it could be written in C though.
However, on the good side I got my InputHandlerDelegate system done, which is going to make coding my GUI system a lot easier. It's actually the first instance where I think that multiple inheritance is fine. Here it is:
class BaseMessageHandler{public: virtual bool OnKeyDown(int VirtKey, long KeyData){ return false; } virtual bool OnKeyUp(int VirtKey, long KeyData){ return false; } virtual bool OnChar(char CharCode, long KeyData){ return false; } virtual bool OnLeftClick(int Keys, int X, int Y, bool DoubleClick){ return false; } virtual bool OnLeftRelease(int Keys, int X, int Y, bool DoubleClick){ return false; } virtual bool OnMiddleClick(int Keys, int X, int Y, bool DoubleClick){ return false; } virtual bool OnMiddleRelease(int Keys, int X, int Y, bool DoubleClick){ return false; } virtual bool OnRightClick(int Keys, int X, int Y, bool DoubleClick){ return false; } virtual bool OnRightRelease(int Keys, int X, int Y, bool DoubleClick){ return false; } virtual bool OnMouseMove(int Keys, int X, int Y){ return false; } virtual bool OnMouseWheel(int Keys, int X, int Y, int ZDelta){ return false; }};class EventHandlerDelegate{ std::vector Handlers;public: const EventHandlerDelegate& operator +=(BaseMessageHandler& Handler) { Handlers.push_back(&Handler); return *this; } const EventHandlerDelegate& operator()(int Message, WPARAM wParam, LPARAM lParam) { static bool LeftWasDoubleClick = false, MiddleWasDoubleClick, RightWasDoubleClick = false; switch(Message) { case WM_KEYDOWN: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnKeyDown((int)wParam, (long)lParam); } break; } case WM_KEYUP: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnKeyUp((int)wParam, (long)lParam); } break; } case WM_CHAR: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnChar((char)wParam, (long)lParam); } break; } case WM_LBUTTONDBLCLK: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnLeftClick((int)wParam, LOWORD(lParam), HIWORD(lParam), true); } LeftWasDoubleClick = true; break; } case WM_LBUTTONDOWN: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnLeftClick((int)wParam, LOWORD(lParam), HIWORD(lParam), false); } LeftWasDoubleClick = false; break; } case WM_LBUTTONUP: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnLeftRelease((int)wParam, LOWORD(lParam), HIWORD(lParam), LeftWasDoubleClick); } break; } case WM_MBUTTONDBLCLK: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnMiddleClick((int)wParam, LOWORD(lParam), HIWORD(lParam), true); } MiddleWasDoubleClick = true; break; } case WM_MBUTTONDOWN: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnMiddleClick((int)wParam, LOWORD(lParam), HIWORD(lParam), false); } MiddleWasDoubleClick = false; break; } case WM_MBUTTONUP: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnMiddleRelease((int)wParam, LOWORD(lParam), HIWORD(lParam), MiddleWasDoubleClick); } break; } case WM_RBUTTONDBLCLK: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnRightClick((int)wParam, LOWORD(lParam), HIWORD(lParam), true); } RightWasDoubleClick = true; break; } case WM_RBUTTONDOWN: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnRightClick((int)wParam, LOWORD(lParam), HIWORD(lParam), false); } RightWasDoubleClick = false; break; } case WM_RBUTTONUP: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnRightRelease((int)wParam, LOWORD(lParam), HIWORD(lParam), RightWasDoubleClick); } break; } case WM_MOUSEMOVE: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnMouseMove((int)wParam, LOWORD(lParam), HIWORD(lParam)); } break; } case 0x020A: { for(std::vector::iterator Iterator = Handlers.begin(); Iterator != Handlers.end(); ++Iterator) { (*Iterator)->OnMouseWheel(LOWORD(wParam), LOWORD(lParam), HIWORD(lParam), HIWORD(wParam)); } break; } } return *this; }};
NOTE: Methinks I'm going to switch to Add(), but I'll probably leave the += operator, but I'm not quite sure it's the best idea. Plus, I'm not so sure about passing the address of a reference; I still have a lot of learning to do [lol].
NOTE 2: I'm still working on the above code; I forgot to include the conditionals. If one of the handlers returns true, then it's going to break out of the loop.
And an example:
class BaseControl{public: virtual bool Create() = 0;};class TestHandler : public BaseMessageHandler, public BaseControl{public: bool Create() { return true; } bool OnKeyDown(int VirtKey, long KeyData) { if(VirtKey == dft::Keys::Decimal) { MessageBox(0, "Buttons, yay!!!", "", MB_OK); return true; } return false; }};
Questions, comments, and suggestions are always welcome!