I was going to post this in the more appropriate Software Engineering forum, but it doesn't seem to be very active. [smile]
Let me sketch the situation (I have omitted any code that's not directly relevant to the problem). I have an (abstract)
Application class with two members:
Window and
Keyboard.
class Application
{
private:
Window window;
Keyboard keyboard;
};
Window is a class that encapsulates the creation and destruction of a WinAPI window and the handling of window messages in a window procedure.
Keyboard is a class that holds the state of the keys and allows event handlers to register to receive various events (OnKeyDown, OnKeyUp, etc).
class KeyboardEventHandler
{
public:
virtual void OnKeyDown(int) = 0;
virtual void OnKeyUp(int) = 0;
};
class Keyboard
{
public:
void AddEventHandler(KeyboardEventHandler*);
};
The problem is that the state and events of
Keyboard are determined by the window messages received in the
Window class, but I don't want
Window to know anything about
Keyboard and vice versa. I should be able to create and test a
Keyboard instance without having a window at all. And having a window require an instance of
Keyboard is even uglier.
I can implement the same event handling 'system' that
Keyboard has for
Window and expose the OnKeyDown/Up events, and have some intermediate class/service take these events and redirect them to
Keyboard, but that leaves me with more ugliness:
- Ideally I want all keyboard input functionality centralized in the
Keyboard class, exposing a Window.OnKeyDown event makes thing confusing.
- To update the keyboard state/events from this intermediate would require either public access to some of its members for solely this particular reason, or I would have to make some sort of friend construction which would create an unnecessary dependency.
Alternatively, I can make 'attaching' a
Window to
Keyboard optional (thus make it work and testable on its own), but it still doesn't feel right (not the best reason, I know).
Or I could drop the entire 'use window messages' thing and go with something like async key states, but that opens up a whole new can of worms.
Any hints on how to keep things as independent as possible, yet making it still work as I want to?
If it wasn't clear: using WinAPI/C++.