WinapiExtension
 All Classes Files Functions Variables Typedefs Pages
WindowMessageHandler.h
1 #ifndef WINAPI_EX_WINDOWMESSAGEHANDLER_H
2 #define WINAPI_EX_WINDOWMESSAGEHANDLER_H
3 
5 template<typename KEY, typename T>
6 class SimpleMap
7 {
8 public:
9  typedef KEY key_type;
10  typedef T mapped_type;
11  typedef std::pair<key_type, mapped_type> value_type;
12  typedef std::vector<value_type> DATA;
13  typedef typename DATA::iterator iterator;
14 
15  size_t size() { return data.size(); }
16  bool empty() { return data.empty(); }
17  iterator begin() { return data.begin(); }
18  iterator end() { return data.end(); }
19  void erase(const iterator& it) { data.erase(it); }
20  void clear() { data.clear(); }
21 
22  iterator find(const key_type& key)
23  {
24  size_t n = data.size();
25  for(size_t i = 0; i < n; ++i)
26  if(data[i].first == key)
27  return data.begin() + i;
28  return data.end();
29  }
30 
31  std::pair<iterator, bool> insert(const value_type& value)
32  {
33  iterator found = find(value.first);
34  if(found != data.end())
35  {
36  found->second = value.second;
37  return std::make_pair(found, false);
38  }
39  data.push_back(value);
40  return std::make_pair(data.end() - 1, true);
41  }
42 
43  mapped_type& operator[] (const key_type& key)
44  {
45  return (*((insert(std::make_pair(key, mapped_type()))).first)).second;
46  }
47 
48  DATA data;
49 };
50 
51 template<typename KEY, typename T>
52 class SimpleMapOfPointers : private SimpleMap<KEY, T>
53 {
54 public:
55  typedef typename SimpleMap<KEY, T>::iterator iterator;
56 
57  ~SimpleMapOfPointers()
58  {
59  iterator end = SimpleMap<KEY, T>::end();
60  for(iterator it = SimpleMap<KEY, T>::begin(); it != end; ++it)
61  delete it->second;
62  }
63 
64  void Add(const KEY& key, const T& mapped)
65  {
66  iterator found = SimpleMap<KEY, T>::find(key);
67  if(found != SimpleMap<KEY, T>::end())
68  {
69  delete found->second;
70  found->second = mapped;
71  }
72  (*this)[key] = mapped;
73  }
74 
75  void Remove(const KEY& key)
76  {
77  iterator found = SimpleMap<KEY, T>::find(key);
78  if(found != SimpleMap<KEY, T>::end())
79  {
80  delete found->second;
81  SimpleMap<KEY, T>::erase(found);
82  }
83  }
84 
85  void RemoveAll()
86  {
87  iterator end = SimpleMap<KEY, T>::end();
88  for(iterator it = SimpleMap<KEY, T>::begin(); it != end; ++it)
89  delete it->second;
90  SimpleMap<KEY, T>::clear();
91  }
92 
93  T Get(const KEY& key)
94  {
95  if(!SimpleMap<KEY, T>::empty())
96  {
97  iterator found = SimpleMap<KEY, T>::find(key);
98  if(found != SimpleMap<KEY, T>::end())
99  return found->second;
100  }
101  return NULL;
102  }
103 };
105 
110 {
111 public:
112  virtual ~WindowMessageHandler() {}
113 
115  template<typename MESSAGE>
116  void Bind(UINT message, void (*function)(MESSAGE&))
117  {
118  AddHandler(MsgKey(message), new FunctionCallback<MESSAGE>(function));
119  }
120 
122  template<typename MESSAGE, typename FUNCTOR>
123  void Bind(UINT message, FUNCTOR function)
124  {
125  AddHandler(MsgKey(message), new FunctorCallback<MESSAGE, FUNCTOR>(function));
126  }
127 
129  template<typename CLASS, typename MESSAGE, typename HANDLER>
130  void Bind(UINT message, void (CLASS::*function)(MESSAGE&), HANDLER* handler)
131  {
132  AddHandler(MsgKey(message), new MemberCallback<CLASS, MESSAGE, HANDLER>(function, handler));
133  }
134 
139  template<typename FUNCTOR>
140  void BindCommand(WORD id, FUNCTOR function, WORD notifyCode = 0)
141  {
142  AddHandler(MsgKey(WM_COMMAND, id, NULL, notifyCode), new FunctorCallback<msgCommand, FUNCTOR>(function));
143  }
144 
146  template<typename FUNCTOR>
147  void BindCommand(HWND hwnd, FUNCTOR function, WORD notifyCode = 0)
148  {
149  AddHandler(MsgKey(WM_COMMAND, 0, hwnd, notifyCode), new FunctorCallback<msgCommand, FUNCTOR>(function));
150  }
151 
153  template<typename CLASS, typename HANDLER>
154  void BindCommand(WORD id, void (CLASS::*function)(msgCommand&), HANDLER* handler, WORD notifyCode = 0)
155  {
156  AddHandler(MsgKey(WM_COMMAND, id, NULL, notifyCode), new MemberCallback<CLASS, msgCommand, HANDLER>(function, handler));
157  }
158 
160  template<typename CLASS, typename HANDLER>
161  void BindCommand(HWND hwnd, void (CLASS::*function)(msgCommand&), HANDLER* handler, WORD notifyCode = 0)
162  {
163  AddHandler(MsgKey(WM_COMMAND, 0, hwnd, notifyCode), new MemberCallback<CLASS, msgCommand, HANDLER>(function, handler));
164  }
165 
170  template<typename FUNCTOR>
171  void BindNotify(UINT_PTR id, UINT notifyCode, FUNCTOR function)
172  {
173  AddHandler(MsgKey(WM_NOTIFY, id, NULL, notifyCode), new FunctorCallback<msgNotify, FUNCTOR>(function));
174  }
175 
177  template<typename FUNCTOR>
178  void BindNotify(HWND hwnd, UINT notifyCode, FUNCTOR function)
179  {
180  AddHandler(MsgKey(WM_NOTIFY, 0, hwnd, notifyCode), new FunctorCallback<msgNotify, FUNCTOR>(function));
181  }
182 
184  template<typename CLASS, typename HANDLER>
185  void BindNotify(UINT_PTR id, UINT notifyCode, void (CLASS::*function)(msgNotify&), HANDLER* handler)
186  {
187  AddHandler(MsgKey(WM_NOTIFY, id, NULL, notifyCode), new MemberCallback<CLASS, msgNotify, HANDLER>(function, handler));
188  }
189 
191  template<typename CLASS, typename HANDLER>
192  void BindNotify(HWND hwnd, UINT notifyCode, void (CLASS::*function)(msgNotify&), HANDLER* handler)
193  {
194  AddHandler(MsgKey(WM_NOTIFY, 0, hwnd, notifyCode), new MemberCallback<CLASS, msgNotify, HANDLER>(function, handler));
195  }
196 
198  void UnBind(UINT message)
199  {
200  RemoveHandler(MsgKey(message));
201  }
202 
204  void UnBindCommand(WORD id, WORD notifyCode = 0)
205  {
206  RemoveHandler(MsgKey(WM_COMMAND, id, NULL, notifyCode));
207  }
208 
210  void UnBindCommand(HWND hwnd, WORD notifyCode = 0)
211  {
212  RemoveHandler(MsgKey(WM_COMMAND, 0, hwnd, notifyCode));
213  }
214 
216  void UnBindNotify(UINT_PTR id, UINT notifyCode = 0)
217  {
218  RemoveHandler(MsgKey(WM_NOTIFY, id, NULL, notifyCode));
219  }
220 
222  void UnBindNotify(HWND hwnd, UINT notifyCode = 0)
223  {
224  RemoveHandler(MsgKey(WM_NOTIFY, 0, hwnd, notifyCode));
225  }
226 
230  bool PassMessageToHandlerFunction(HWND hwnd, UINT message, WPARAM wp, LPARAM lp, LRESULT& result)
231  {
232  // New style, use functor message handlers
233  Functor* handler = NULL;
234 
235  if(message == WM_COMMAND)
236  {
237  handler = GetHandler(MsgKey(message, LOWORD(wp), (HWND)lp, HIWORD(wp)));
238  }
239  else if(message == WM_NOTIFY)
240  {
241  NMHDR* header = (NMHDR*)lp;
242  handler = GetHandler(MsgKey(message, header->idFrom, header->hwndFrom, header->code));
243  }
244  if(handler == NULL)
245  {
246  handler = GetHandler(MsgKey(message));
247  }
248 
249  if(handler)
250  return (*handler)(hwnd, message, wp, lp, result, this);
251 
252  return false;
253  }
254 
256  virtual LRESULT OnMessage(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) = 0;
257 private:
258  // functor holds either a global function, function object or a member function
259  struct Functor
260  {
261  virtual ~Functor() {}
262 
263  virtual bool operator() (HWND hwnd, UINT message, WPARAM wp, LPARAM lp, LRESULT& result, WindowMessageHandler* origin) = 0;
264  };
265 
266  // functor to global function
267  template<typename MESSAGE>
268  struct FunctionCallback : public Functor
269  {
270  typedef void (*FUNCTION)(MESSAGE&);
271 
272  FunctionCallback(const FUNCTION& f)
273  : function(f)
274  {}
275 
276  virtual bool operator() (HWND hwnd, UINT message, WPARAM wp, LPARAM lp, LRESULT& result, WindowMessageHandler* origin)
277  {
278  MESSAGE m;
279  m.Init(hwnd, message, wp, lp);
280  m.messageHandler = origin;
281 
282  function(m);
283 
284  if(m.resultSet && result)
285  result = m.result;
286  return m.resultSet;
287  }
288 
289  FUNCTION function;
290  };
291 
292  // functor to function object
293  template<typename MESSAGE, typename FUNCTOR>
294  struct FunctorCallback : public Functor
295  {
296  FunctorCallback(const FUNCTOR& f)
297  : function(f)
298  {}
299 
300  virtual bool operator() (HWND hwnd, UINT message, WPARAM wp, LPARAM lp, LRESULT& result, WindowMessageHandler* origin)
301  {
302  MESSAGE m;
303  m.Init(hwnd, message, wp, lp);
304  m.messageHandler = origin;
305 
306  function(m);
307 
308  if(m.resultSet && result)
309  result = m.result;
310  return m.resultSet;
311  }
312 
313  FUNCTOR function;
314  };
315 
316  // functor to member function
317  template<typename CLASS, typename MESSAGE, typename HANDLER>
318  struct MemberCallback : public Functor
319  {
320  typedef void (CLASS::*FUNCTION)(MESSAGE& m);
321 
322  MemberCallback(FUNCTION f, HANDLER* inst)
323  : function(f)
324  , instance(inst)
325  {}
326 
327  virtual bool operator() (HWND hwnd, UINT message, WPARAM wp, LPARAM lp, LRESULT& result, WindowMessageHandler* origin)
328  {
329  MESSAGE m;
330  m.Init(hwnd, message, wp, lp);
331  m.messageHandler = origin;
332 
333  (instance->*function)(m);
334 
335  if(m.resultSet && result)
336  result = m.result;
337  return m.resultSet;
338  }
339 
340  FUNCTION function;
341  HANDLER* instance;
342  };
343 
344  // Identification of a Windows message, to be used in std::map or something equivalent
345  struct MsgKey
346  {
347  UINT message;
348  // for WM_COMMAND/WM_NOTIFY
349  UINT_PTR id;
350  HWND hwnd;
351  UINT notifyCode;
352 
353  MsgKey(UINT pMessage, UINT_PTR pID = 0, HWND pHwnd = NULL, UINT pNotifyCode = 0)
354  : message(pMessage)
355  , id(pID)
356  , hwnd(pHwnd)
357  , notifyCode(pNotifyCode)
358  {}
359 
360  bool operator<(const MsgKey& other)
361  {
362  if(message != other.message)
363  return message < other.message;
364  if(hwnd == NULL && id != other.id)
365  return id < other.id;
366  if(id == 0 && hwnd != other.hwnd)
367  return hwnd < other.hwnd;
368  return notifyCode < other.notifyCode;
369  }
370 
371  bool operator== (const MsgKey& other)
372  {
373  return message == other.message
374  // important: match only id or hwnd, not both
375  && (hwnd == NULL ? id == other.id : true)
376  && (id == 0 ? hwnd == other.hwnd : true)
377  && notifyCode == other.notifyCode;
378  }
379  };
380 
381  // the stuff below could be replaced with something sophisticated (hashmap?)
382  SimpleMapOfPointers<MsgKey, Functor*> handlers;
383 
384  void AddHandler(const MsgKey& key, Functor* handler)
385  {
386  handlers.Add(key, handler);
387  }
388 
389  void RemoveHandler(const MsgKey& key)
390  {
391  handlers.Remove(key);
392  }
393 
394  Functor* GetHandler(const MsgKey& key)
395  {
396  return handlers.Get(key);
397  }
398 };
399 
400 #endif