Wxwidgets Source Analysis (3)-Message mapping table

Source: Internet
Author: User
Tags wxwidgets

Tag: is the Connect widget Comm cal specified static public hash

Directory

    • Message map Table
      • Static message map table
      • Static message mapping Table processing procedure
      • Dynamic Message map Table
      • Process of dynamic message map table processing
Message map Table

The message is the core of the GUI program, and all the operational behavior is communicated through the message.

Static message map table

Use static eventtable to bind the event number to the processing code, using the example:

// 声明class debugWXFrame: public wxFrame{    DECLARE_EVENT_TABLE()};// 实现BEGIN_EVENT_TABLE(debugWXFrame,wxFrame)    EVT_MENU(ID_MenuUser, debugWXFrame::OnCheckMenu)END_EVENT_TABLE()

Look at the definition first wxDECLARE_EVENT_TABLE to declare some data in the current class, mostly static data, and provide GetEventTable access to the table;

#define DECLARE_EVENT_TABLE()                          wxDECLARE_EVENT_TABLE();#define wxDECLARE_EVENT_TABLE()                                             private:                                                                    static const wxEventTableEntry sm_eventTableEntries[];              protected:                                                                  static const wxEventTable        sm_eventTable;                         virtual const wxEventTable*      GetEventTable() const;                 static wxEventHashTable          sm_eventHashTable;                     virtual wxEventHashTable&        GetEventHashTable() const

The following is an implementation that initializes these static variables, and all message definitions are located wxBEGIN_EVENT_TABLE and END_EVENT_TABLE between:

    1. sm_eventTableEntriesSave the message map table, which is the message ID and message processing function relationship;
    2. The implementation method is used by the GetEventTable caller;
    3. sm_eventHashTableFor saving Hashtable, the lookup rate will increase;
#define BEGIN_EVENT_TABLE(a,b)                         wxBEGIN_EVENT_TABLE(a,b)#define END_EVENT_TABLE()                              wxEND_EVENT_TABLE()#define wxBEGIN_EVENT_TABLE(theClass, baseClass)     const wxEventTable theClass::sm_eventTable =         { &baseClass::sm_eventTable, &theClass::sm_eventTableEntries[0] };     const wxEventTable *theClass::GetEventTable() const         { return &theClass::sm_eventTable; }     wxEventHashTable theClass::sm_eventHashTable(theClass::sm_eventTable);     wxEventHashTable &theClass::GetEventHashTable() const         { return theClass::sm_eventHashTable; }     const wxEventTableEntry theClass::sm_eventTableEntries[] = { #define wxEND_EVENT_TABLE()     wxDECLARE_EVENT_TABLE_TERMINATOR() };

In wxBEGIN_EVENT_TABLE and END_EVENT_TABLE between is the message processing item, for example EVT_MENU(ID_MenuUser, debugWXFrame::OnCheckMenu) , above is an item, we can expand this:

// 用户使用这个宏来定义事件映射#define EVT_MENU(winid, func) wx__DECLARE_EVT1(wxEVT_MENU, winid, wxCommandEventHandler(func))// 事件映射内部宏#define wx__DECLARE_EVT2(evt, id1, id2, fn)     wxDECLARE_EVENT_TABLE_ENTRY(evt, id1, id2, fn, NULL),#define wx__DECLARE_EVT1(evt, id, fn)     wx__DECLARE_EVT2(evt, id, wxID_ANY, fn)// 根据传递进来的参数创建一个wxEventTableEntry对象#define wxDECLARE_EVENT_TABLE_ENTRY(type, winid, idLast, fn, obj)     wxEventTableEntry(type, winid, idLast, wxNewEventTableFunctor(type, fn), obj)

Then the EVT_MENU(ID_MenuUser, debugWXFrame::OnCheckMenu) expansion is followed by:

wxEventTableEntry(wxEVT_MENU, winid, wxID_ANY,         wxNewEventTableFunctor(wxEVT_MENU, wxCommandEventHandler(fn)), NULL)

wxNewEventTableFunctorUsed to instantiate an wxObjectEventFunctor object wxCommandEventHandler for use in a strongly-forwarded message processing function wxNewEventTableFunctor .

#define wxCommandEventHandler(func)     wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)#define wxEVENT_HANDLER_CAST( functype, func )     ( wxObjectEventFunction )( wxEventFunction )wxStaticCastEvent( functype, &func )inline wxObjectEventFunctor *wxNewEventTableFunctor(const wxEventType& WXUNUSED(evtType),                       wxObjectEventFunction method){    return new wxObjectEventFunctor(method, NULL);}

This allows you to statically create multiple wxEventTableEntry objects and add them to the sm_eventTableEntries .

Static message mapping Table processing procedure

The message processing process wxEvtHandler::TryHereOnly calls the static table query processing:

bool wxEvtHandler::TryHereOnly(wxEvent& event){    // Then static per-class event tables    if ( GetEventHashTable().HandleEvent(event, this) )        return true;}

The GetEventHashTable method above returns an wxEventHashTable object and then invokes the object's HandleEvent method:

    1. wxEventHashTableThe table is segmented according to the message type, so that you can quickly find the table of the specified type;
    2. Iterates over a table of the specified type, for each wxEventTableEntry callProcessEventIfMatchesId
bool wxEventHashTable::HandleEvent(wxEvent &event, wxEvtHandler *self){    // Find all entries for the given event type.    wxEventType eventType = event.GetEventType();    const EventTypeTablePointer eTTnode = m_eventTypeTable[eventType % m_size];    if (eTTnode && eTTnode->eventType == eventType)    {        const wxEventTableEntryPointerArray&            eventEntryTable = eTTnode->eventEntryTable;        const size_t count = eventEntryTable.GetCount();        for (size_t n = 0; n < count; n++)        {            const wxEventTableEntry& entry = *eventEntryTable[n];            if ( wxEvtHandler::ProcessEventIfMatchesId(entry, self, event) )                return true;        }    }    return false;}

wxEvtHandler::ProcessEventIfMatchesIdThe processing flow is as follows:

    1. Checks whether the currently received message matches this item wxEventTableEntryBase
    2. Call the user's handler function m_fn execution, here m_fn is also after several layers of encapsulation, interested in continuing to follow.
bool wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,                                           wxEvtHandler *handler,                                           wxEvent& event){    int tableId1 = entry.m_id,        tableId2 = entry.m_lastId;    // match only if the event type is the same and the id is either -1 in    // the event table (meaning "any") or the event id matches the id    // specified in the event table either exactly or by falling into    // range between first and last    if ((tableId1 == wxID_ANY) ||        (tableId2 == wxID_ANY && tableId1 == event.GetId()) ||        (tableId2 != wxID_ANY &&         (event.GetId() >= tableId1 && event.GetId() <= tableId2)))    {        event.Skip(false);        event.m_callbackUserData = entry.m_callbackUserData;        (*entry.m_fn)(handler, event);        if (!event.GetSkipped())            return true;    }    return false;}
Dynamic Message map Table

The addition and deletion of dynamic mapping table entries is carried out wxEvtHandler::DoBind and wxEvtHandler::DoUnbind executed, and Wxwidgets provides a variety of interfaces to perform this operation.

It is important to note that if the object is passed in wxEvtHandler , it is processed by invoking the user-specified wxEvtHandler object for processing, and if not specified, it is processed directly using the current wxEvtHandler object.

There are interfaces that provide similar functionality, but they are Connect Connect more complex to use, and it is recommended that all subsequent code be used Bind接口 , not to repeat them here.

BindAn interface is a template function that provides three types of interfaces:

    1. Directly bind the global function, at this time only the event type and function parameters must be, recommended to use ;
    2. Binding Funtor function, users need to use their own wxNewEventFunctor encapsulation, not recommended ;
    3. The use of Class intrinsics, as well as the need to specify a class pointer, is recommended .

Three types of interfaces are declared as follows:

template <typename EventTag, typename EventArg>void Bind(const EventTag& eventType,          void (*function)(EventArg &),          int winid = wxID_ANY,          int lastId = wxID_ANY,          wxObject *userData = NULL)          template <typename EventTag, typename Functor>void Bind(const EventTag& eventType,          const Functor &functor,          int winid = wxID_ANY,          int lastId = wxID_ANY,          wxObject *userData = NULL)          template <typename EventTag, typename Class,           typename EventArg, typename EventHandler>void Bind(const EventTag &eventType,          void (Class::*method)(EventArg &),          EventHandler *handler,          int winid = wxID_ANY,          int lastId = wxID_ANY,          wxObject *userData = NULL)
Process of dynamic message map table processing

Same as static message entry, when wxEvtHandler::TryHereOnly getting called:

bool wxEvtHandler::TryHereOnly(wxEvent& event){    // Handle per-instance dynamic event tables first    if ( m_dynamicEvents && SearchDynamicEventTable(event) )        return true;}

Dynamic table lookup is relatively simple, the dynamic message table exists in the list m_dynamicEvents , as long as the list of every item out of the chain ProcessEventIfMatchesId to call on it.

bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event ){    wxList::compatibility_iterator node = m_dynamicEvents->GetFirst();    while (node)    {        wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();        node = node->GetNext();        if ( event.GetEventType() == entry->m_eventType )        {            wxEvtHandler *handler = entry->m_fn->GetEvtHandler();            if ( !handler )               handler = this;            if ( ProcessEventIfMatchesId(*entry, handler, event) )                return true;        }    }    return false;}

Wxwidgets Source Analysis (3)-Message mapping table

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.