The normal order of event table searching by ProcessEvent is as follows:
1. If the object is disabled (via a call to wxEvtHandler::SetEvtHandlerEnabled) the function skips
to step (6).
2. If the object is a wxWindow, ProcessEvent is recursively called on the window's wxValidator.
If this returns true, the function exits.
3. SearchEventTable is called for this event handler. If this fails, the base class table is tried,
and so on until no more tables exist or an appropriate function was found, in which case the function
exits.
4. The search is applied down the entire chain of event handlers (usually the chain has a length of
one). If this succeeds, the function exits.
5. If the object is a wxWindow and the event is set to set to propagate (in the library only wxCommandEvent
based events are set to propagate), ProcessEvent is recursively applied to the parent window's event handler.
If this returns true, the function exits.
bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
// allow the application to hook into event processing
if ( wxTheApp )
{
int rc = wxTheApp->FilterEvent(event);
if ( rc != -1 )
{
wxASSERT_MSG( rc == 1 || rc == 0,
_T("unexpected wxApp::FilterEvent return value") );
return rc != 0;
}
//else: proceed normally
}
// An event handler can be enabled or disabled
if ( GetEvtHandlerEnabled() )
{
// if we have a validator, it has higher priority than our own event
// table
if ( TryValidator(event) )
return true;
// Handle per-instance dynamic event tables first
if ( m_dynamicEvents && SearchDynamicEventTable(event) )
return true;
// Then static per-class event tables
if ( GetEventHashTable().HandleEvent(event, this) )
return true;
}
// Try going down the event handler chain
if ( GetNextHandler() )
{
if ( GetNextHandler()->ProcessEvent(event) )
return true;
}
// Finally propagate the event upwards the window chain and/or to the
// application object as necessary
return TryParent(event);
}
Only command events are recursively applied to the parents event handler in the library itself.
There are two ways to define a entirely new event class: one is to use existing event classes, another
is to derive from wxEvent or wxCommandEvent.
Using existing event classes
If you want to use a wxCommandEvent with a new event type, you can then use one of the generic event
table macros, without having to define a new macro yourself. This also has the advantage that you won't
have to define a new wxEvent::Clone() method for posting events between threads etc.
DECLARE_EVENT_TYPE(wxEVT_MY_EVENT, -1)
DEFINE_EVENT_TYPE(wxEVT_MY_EVENT)
// user code intercepting the event
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU (wxID_EXIT, MyFrame::OnExit)
// ....
EVT_COMMAND (ID_MY_WINDOW, wxEVT_MY_EVENT, MyFrame::OnMyEvent)
END_EVENT_TABLE()
void MyFrame::OnMyEvent( wxCommandEvent &event )
{
// do something
wxString text = event.GetText();
}
// user code sending the event
void MyWindow::SendEvent()
{
wxCommandEvent event( wxEVT_MY_EVENT, GetId() );
event.SetEventObject( this );
// Give it some contents
event.SetText( wxT("Hallo") );
// Send it
GetEventHandler()->ProcessEvent( event );
}
Defining your own event class
Under certain circumstances, it will be required to define your own event class e.g.
for sending more complex data from one place to another. Apart from defining your event
class, you will also need to define your own event table macro (which is quite long).
Watch out to put in enough casts to the inherited event function.
// code defining event
class wxPlotEvent: public wxNotifyEvent
{
public:
wxPlotEvent( wxEventType commandType = wxEVT_NULL, int id = 0 );
// accessors
wxPlotCurve *GetCurve()
{ return m_curve; }
// required for sending with wxPostEvent()
wxEvent* Clone();
private:
wxPlotCurve *m_curve;
};
DECLARE_EVENT_MACRO( wxEVT_PLOT_ACTION, -1 )
typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&);
#define EVT_PLOT(id, fn) /
DECLARE_EVENT_TABLE_ENTRY( wxEVT_PLOT_ACTION, id, -1, /
(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) /
wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ),
// code implementing the event type and the event class
DEFINE_EVENT_TYPE( wxEVT_PLOT_ACTION )
wxPlotEvent::wxPlotEvent( ...
// user code intercepting the event
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_PLOT (ID_MY_WINDOW, MyFrame::OnPlot)
END_EVENT_TABLE()
void MyFrame::OnPlot( wxPlotEvent &event )
{
wxPlotCurve *curve = event.GetCurve();
}
// user code sending the event
void MyWindow::SendEvent()
{
wxPlotEvent event( wxEVT_PLOT_ACTION, GetId() );
event.SetEventObject( this );
event.SetCurve( m_curve );
GetEventHandler()->ProcessEvent( event );
}
1. If the object is disabled (via a call to wxEvtHandler::SetEvtHandlerEnabled) the function skips
to step (6).
2. If the object is a wxWindow, ProcessEvent is recursively called on the window's wxValidator.
If this returns true, the function exits.
3. SearchEventTable is called for this event handler. If this fails, the base class table is tried,
and so on until no more tables exist or an appropriate function was found, in which case the function
exits.
4. The search is applied down the entire chain of event handlers (usually the chain has a length of
one). If this succeeds, the function exits.
5. If the object is a wxWindow and the event is set to set to propagate (in the library only wxCommandEvent
based events are set to propagate), ProcessEvent is recursively applied to the parent window's event handler.
If this returns true, the function exits.
bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
// allow the application to hook into event processing
if ( wxTheApp )
{
int rc = wxTheApp->FilterEvent(event);
if ( rc != -1 )
{
wxASSERT_MSG( rc == 1 || rc == 0,
_T("unexpected wxApp::FilterEvent return value") );
return rc != 0;
}
//else: proceed normally
}
// An event handler can be enabled or disabled
if ( GetEvtHandlerEnabled() )
{
// if we have a validator, it has higher priority than our own event
// table
if ( TryValidator(event) )
return true;
// Handle per-instance dynamic event tables first
if ( m_dynamicEvents && SearchDynamicEventTable(event) )
return true;
// Then static per-class event tables
if ( GetEventHashTable().HandleEvent(event, this) )
return true;
}
// Try going down the event handler chain
if ( GetNextHandler() )
{
if ( GetNextHandler()->ProcessEvent(event) )
return true;
}
// Finally propagate the event upwards the window chain and/or to the
// application object as necessary
return TryParent(event);
}
Only command events are recursively applied to the parents event handler in the library itself.
There are two ways to define a entirely new event class: one is to use existing event classes, another
is to derive from wxEvent or wxCommandEvent.
Using existing event classes
If you want to use a wxCommandEvent with a new event type, you can then use one of the generic event
table macros, without having to define a new macro yourself. This also has the advantage that you won't
have to define a new wxEvent::Clone() method for posting events between threads etc.
DECLARE_EVENT_TYPE(wxEVT_MY_EVENT, -1)
DEFINE_EVENT_TYPE(wxEVT_MY_EVENT)
// user code intercepting the event
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU (wxID_EXIT, MyFrame::OnExit)
// ....
EVT_COMMAND (ID_MY_WINDOW, wxEVT_MY_EVENT, MyFrame::OnMyEvent)
END_EVENT_TABLE()
void MyFrame::OnMyEvent( wxCommandEvent &event )
{
// do something
wxString text = event.GetText();
}
// user code sending the event
void MyWindow::SendEvent()
{
wxCommandEvent event( wxEVT_MY_EVENT, GetId() );
event.SetEventObject( this );
// Give it some contents
event.SetText( wxT("Hallo") );
// Send it
GetEventHandler()->ProcessEvent( event );
}
Defining your own event class
Under certain circumstances, it will be required to define your own event class e.g.
for sending more complex data from one place to another. Apart from defining your event
class, you will also need to define your own event table macro (which is quite long).
Watch out to put in enough casts to the inherited event function.
// code defining event
class wxPlotEvent: public wxNotifyEvent
{
public:
wxPlotEvent( wxEventType commandType = wxEVT_NULL, int id = 0 );
// accessors
wxPlotCurve *GetCurve()
{ return m_curve; }
// required for sending with wxPostEvent()
wxEvent* Clone();
private:
wxPlotCurve *m_curve;
};
DECLARE_EVENT_MACRO( wxEVT_PLOT_ACTION, -1 )
typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&);
#define EVT_PLOT(id, fn) /
DECLARE_EVENT_TABLE_ENTRY( wxEVT_PLOT_ACTION, id, -1, /
(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) /
wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ),
// code implementing the event type and the event class
DEFINE_EVENT_TYPE( wxEVT_PLOT_ACTION )
wxPlotEvent::wxPlotEvent( ...
// user code intercepting the event
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_PLOT (ID_MY_WINDOW, MyFrame::OnPlot)
END_EVENT_TABLE()
void MyFrame::OnPlot( wxPlotEvent &event )
{
wxPlotCurve *curve = event.GetCurve();
}
// user code sending the event
void MyWindow::SendEvent()
{
wxPlotEvent event( wxEVT_PLOT_ACTION, GetId() );
event.SetEventObject( this );
event.SetCurve( m_curve );
GetEventHandler()->ProcessEvent( event );
}
本文详细介绍了wxWidgets中事件处理的流程,包括事件的传递、过滤、处理等关键步骤,并提供了定义自定义事件类的方法。

被折叠的 条评论
为什么被折叠?



