Eugene, one more thing when you implement the GUI library. I ALWAYS hated the message maps from MFC/WTL. So now I came up with a quite cute method of automating registering of events for a given window.
(this should work for registering messages, etc.) It's very flexible. In other words, when you add an event for wnd_widget, it does not couple the header file wnd_widget.h to the resource file (think MFC for a moment ;) ) So, in case you modify the ID of a resource, all you have to do is recompile the source file (wnd_widget.cpp), not the whole files depending on wnd_widget.h. So, lets get down to it: Here's how to register an event for window test: // test.h class test : public wnd< test> { public: event_base on_ok(); }; // test.cpp #include "resource.h" test::event_base test::on_ok() { // [do whatever you like to handle the event] // this is how we say that on_ok should handle the ID_OK event // return event< ID_OK, &test::on_ok>(); } P.S. you have no idea how many workarounds/ twists I had to do to make this compile on VC6 !!! ------------------- #include <map> #include <algorithm> template< class initializer_class> struct wnd_initializer { struct init { init() { initializer_class::do_initialize(); } }; static init s_init; }; template< class initializer_class> wnd_initializer< initializer_class>::init wnd_initializer< initializer_class>::s_init; template< class wnd_class> struct wnd { struct event_base; typedef event_base (wnd_class::*func)(); // ... prevent wnd_event_base from being constructed directly struct event_base { protected: event_base( int id, func f, void* ) : m_id( id) { } public: event_base( const event_base& other) : m_id( other.m_id){} private: int m_id; // VC6 chokes on this //func m_f; }; private: template< int id, func f> struct event_initializer { static void do_initialize() { wnd< wnd_class>::s_events.add_event( id, new func_wrapper<f>()); } }; protected: template< int id, func f> struct event : public event_base, private wnd_initializer< event_initializer<id, f> > { typedef wnd_initializer< event_initializer<id, f> > initializer; event() : event_base( id, f, (void*)&initializer::s_init) { } }; private: // keeping the member function pointers as data members // (example : struct keeper { func m_f; }) makes VC6 choke struct func_wrapper_base { virtual void call_event( wnd_class *) const = 0; }; template< func f> struct func_wrapper : public func_wrapper_base { virtual void call_event( wnd_class *p) const { (p->*f)(); } }; public: // contains the events for this window struct events_for_wnd { typedef std::map< int, func_wrapper_base*> events_coll; void add_event( int id, func_wrapper_base * f) { m_events[ id] = f; } const events_coll & get_events() const { return m_events; } void call_event( int id, wnd_class * p) const { typedef typename events_coll::const_iterator const_iterator; const_iterator found = m_events.find( id); if ( found != m_events.end() ) if ( p != 0) found->second->call_event( p); } ~events_for_wnd() { std::for_each( m_events.begin(), m_events.end(), do_delete); } private: static void do_delete( const std::pair< const int, func_wrapper_base *> &val) { delete val.second; } private: events_coll m_events; }; static events_for_wnd s_events; }; template< class wnd_class> wnd< wnd_class>::events_for_wnd wnd< wnd_class>::s_events; // test.h class test : public wnd< test> { public: event_base on_ok(); event_base on_cancel(); event_base on_apply(); }; // test.cpp #include <iostream> #define ID_OK 1 #define ID_CANCEL 2 #define ID_APPLY 3 test::event_base test::on_ok() { std::cout << "ON OK event called" << std::endl; // this is how we say that on_ok should handle the ID_OK event // return event< ID_OK, &test::on_ok>(); } test::event_base test::on_cancel() { std::cout << "ON CANCEL event called " << std::endl; // this is how we say that on_ok should handle the ID_CANCEL event // return event< ID_CANCEL, &test::on_cancel>(); } test::event_base test::on_apply() { std::cout << "ON APPLY event called " << std::endl; // this is how we say that on_ok should handle the ID_APPLY event // return event< ID_APPLY, &test::on_apply>(); } int main(int argc, char* argv[]) { test t; typedef test::events_for_wnd::events_coll coll; const coll & events = test::s_events.get_events(); coll::const_iterator first = events.begin(), last = events.end(); while ( first != last) { int id = first->first; std::cout << "event handler for id " << id << " is in place" << std::endl; // calling this event for 't': test::s_events.call_event( id, &t); ++first; } std::cin.get(); return 0; } _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost