Seperating input and window

Started by
3 comments, last by Wan 14 years, 2 months ago
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.
class Window
{

};
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++.
Advertisement
maybe have a look at:

Quote:WH_KEYBOARD_LL Hook

The WH_KEYBOARD_LL hook enables you to monitor keyboard input events about to be posted in a thread input queue.

For more information, see the LowLevelKeyboardProc function.
MSDN
As long as input events originate with the window, there is going to have to be some layer of abstraction that knows about both of them. You could use abstract interfaces to loosen some of the dependencies (a la the Dependency Inversion Principle), but that might overcomplicate things.

How were you planning on getting input without Keyboard knowing about a window?
I think a keyboard hook is probably overkill...

You could allow the Window to accept generic "WndProc hooks" which are simply boost::functions that it keeps in a list and then calls whenever a windows message arrives. Then the Keyboard class could register itself with the Window class to receive notifications about window messages (discarding anything but keyboard-related ones).

You could use the same mechanism for WM_INPUT-based input devices as well.
Thanks all for the replies. [smile]

Quote:Original post by flery
keyboard hook

Like Codeka said, I would consider that overkill. I would like to keep things as simple as possible.

Quote:Original post by theOcelot
Dependency Inversion Principle

Funny enough, I actually looked at that before making this post, see if I could implement the ideas presented in the paper.

Quote:Original post by theOcelot
How were you planning on getting input without Keyboard knowing about a window?

No doubt there needs to be some sort of 'connection' between the two, but I was hoping I wouldn't need such a direct dependency.

Quote:Original post by Codeka
You could allow the Window to accept generic "WndProc hooks" which are simply boost::functions that it keeps in a list and then calls whenever a windows message arrives. Then the Keyboard class could register itself with the Window class to receive notifications about window messages (discarding anything but keyboard-related ones).

Yeah, that's sort of what I have right now, but without using Boost. I think I'll stick to that mechanism for now.

This topic is closed to new replies.

Advertisement