今天我们来比较 MFC 和 wxWidgets 的最核心的代码,也就是MFC的消息映射和wxWidgets的事件表。
1.MFC 中的消息映射宏
DECLARE_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(theClass, baseClass)
END_MESSAGE_MAP()
展开后代码如下:
#ifdef _AFXDLL
#define DECLARE_MESSAGE_MAP() /
private: /
static const AFX_MSGMAP_ENTRY _messageEntries[]; /
protected: /
static AFX_DATA const AFX_MSGMAP messageMap; /
static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); /
virtual const AFX_MSGMAP* GetMessageMap() const; /
#else
#define DECLARE_MESSAGE_MAP() /
private: /
static const AFX_MSGMAP_ENTRY _messageEntries[]; /
protected: /
static AFX_DATA const AFX_MSGMAP messageMap; /
virtual const AFX_MSGMAP* GetMessageMap() const; /
#endif
#ifdef _AFXDLL
# define BEGIN_MESSAGE_MAP(theClass, baseClass) /
const AFX_MSGMAP* PASCAL theClass::_GetBaseMessageMap() /
{ return &baseClass::messageMap; } /
const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return &theClass::messageMap; } /
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = /
{ &theClass::_GetBaseMessageMap, &theClass::_messageEntries[0] }; /
AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = /
{ /
#else
# define BEGIN_MESSAGE_MAP(theClass, baseClass) /
const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return &theClass::messageMap; } /
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = /
{ &baseClass::messageMap, &theClass::_messageEntries[0] }; /
AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = /
{ /
#endif
# define END_MESSAGE_MAP() /
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } /
}; /
其中 AFX_MSGMAP 和 AFX_MSGMAP_ENTRY 的声明如下:
struct AFX_MSGMAP
{
#ifdef _AFXDLL // use shared dll
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
#else
const AFX_MSGMAP* pBaseMap;
#endif
const AFX_MSGMAP_ENTRY* lpEntries;
};
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
2.wxWidgets 中的事件表宏
DECLARE_EVENT_TABLE()
BEGIN_EVENT_TABLE(theClass, baseClass)
END_EVENT_TABLE()
展开后代码如下:
#define DECLARE_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;
#define BEGIN_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 END_EVENT_TABLE() DECLARE_EVENT_TABLE_ENTRY( wxEVT_NULL, 0, 0, 0, 0 ) };
struct WXDLLIMPEXP_BASE wxEventTable
{
const wxEventTable *baseTable; // base event table (next in chain)
const wxEventTableEntry *entries; // bottom of entry array
};
class WXDLLIMPEXP_BASE wxEventHashTable
{
private:
// Internal data structs
struct EventTypeTable
{
wxEventType eventType;
wxEventTableEntryPointerArray eventEntryTable;
};
typedef EventTypeTable* EventTypeTablePointer;
public:
// Constructor, needs the event table it needs to hash later on.
// Note: hashing of the event table is not done in the constructor as it
// can be that the event table is not yet full initialize, the hash
// will gets initialized when handling the first event look-up request.
wxEventHashTable(const wxEventTable &table);
// Destructor.
~wxEventHashTable();
// Handle the given event, in other words search the event table hash
// and call self->ProcessEvent() if a match was found.
bool HandleEvent(wxEvent &event, wxEvtHandler *self);
// Clear table
void Clear();
// Clear all tables
static void ClearAll();
// Rebuild all tables
static void ReconstructAll();
protected:
// Init the hash table with the entries of the static event table.
void InitHashTable();
// Helper funtion of InitHashTable() to insert 1 entry into the hash table.
void AddEntry(const wxEventTableEntry &entry);
// Allocate and init with null pointers the base hash table.
void AllocEventTypeTable(size_t size);
// Grow the hash table in size and transfer all items currently
// in the table to the correct location in the new table.
void GrowEventTypeTable();
protected:
const wxEventTable &m_table;
bool m_rebuildHash;
size_t m_size;
EventTypeTablePointer *m_eventTypeTable;
static wxEventHashTable* sm_first;
wxEventHashTable* m_previous;
wxEventHashTable* m_next;
DECLARE_NO_COPY_CLASS(wxEventHashTable)
};