1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Event classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "event.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  37         #include "wx/control.h" 
  46     #include "wx/validate.h" 
  49 // ---------------------------------------------------------------------------- 
  51 // ---------------------------------------------------------------------------- 
  53     IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler
, wxObject
) 
  54     IMPLEMENT_ABSTRACT_CLASS(wxEvent
, wxObject
) 
  55     IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent
, wxEvent
) 
  58         IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent
, wxEvent
) 
  59         IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent
, wxCommandEvent
) 
  60         IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent
, wxCommandEvent
) 
  61         IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent
, wxEvent
) 
  62         IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent
, wxEvent
) 
  63         IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent
, wxEvent
) 
  64         IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent
, wxEvent
) 
  65         IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent
, wxEvent
) 
  66         IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent
, wxEvent
) 
  67         IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent
, wxEvent
) 
  68         IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent
, wxEvent
) 
  69         IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent
, wxEvent
) 
  70         IMPLEMENT_DYNAMIC_CLASS(wxShowEvent
, wxEvent
) 
  71         IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent
, wxEvent
) 
  72         IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent
, wxEvent
) 
  73         IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent
, wxEvent
) 
  74         IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent
, wxEvent
) 
  75         IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent
, wxEvent
) 
  76         IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent
, wxEvent
) 
  77         IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent
, wxEvent
) 
  78         IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent
, wxEvent
) 
  79         IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent
, wxCommandEvent
) 
  80         IMPLEMENT_DYNAMIC_CLASS(wxNavigationKeyEvent
, wxCommandEvent
) 
  81         IMPLEMENT_DYNAMIC_CLASS(wxPaletteChangedEvent
, wxEvent
) 
  82         IMPLEMENT_DYNAMIC_CLASS(wxQueryNewPaletteEvent
, wxEvent
) 
  83         IMPLEMENT_DYNAMIC_CLASS(wxWindowCreateEvent
, wxEvent
) 
  84         IMPLEMENT_DYNAMIC_CLASS(wxWindowDestroyEvent
, wxEvent
) 
  87     const wxEventTable 
*wxEvtHandler::GetEventTable() const 
  88         { return &wxEvtHandler::sm_eventTable
; } 
  90     const wxEventTable 
wxEvtHandler::sm_eventTable 
= 
  91         { (const wxEventTable 
*)NULL
, &wxEvtHandler::sm_eventTableEntries
[0] }; 
  93     const wxEventTableEntry 
wxEvtHandler::sm_eventTableEntries
[] = 
  94         { { 0, 0, 0, (wxObjectEventFunction
) NULL
, (wxObject
*) NULL 
} }; 
  97 // ---------------------------------------------------------------------------- 
  99 // ---------------------------------------------------------------------------- 
 101 // To put pending event handlers 
 102 wxList 
*wxPendingEvents 
= (wxList 
*)NULL
; 
 105     // protects wxPendingEvents list 
 106     wxCriticalSection 
*wxPendingEventsLocker 
= (wxCriticalSection 
*)NULL
; 
 109 // ============================================================================ 
 111 // ============================================================================ 
 113 // ---------------------------------------------------------------------------- 
 115 // ---------------------------------------------------------------------------- 
 118  * General wxWindows events, covering 
 119  * all interesting things that might happen (button clicking, resizing, 
 120  * setting text in widgets, etc.). 
 122  * For each completely new event type, derive a new event class. 
 126 wxEvent::wxEvent(int theId
) 
 128     m_eventType 
= wxEVT_NULL
; 
 129     m_eventObject 
= (wxObject 
*) NULL
; 
 133     m_callbackUserData 
= (wxObject 
*) NULL
; 
 134     m_isCommandEvent 
= FALSE
; 
 137 void wxEvent::CopyObject(wxObject
& object_dest
) const 
 139     wxEvent 
*obj 
= (wxEvent 
*)&object_dest
; 
 140     wxObject::CopyObject(object_dest
); 
 142     obj
->m_eventType 
= m_eventType
; 
 143     obj
->m_eventObject 
= m_eventObject
; 
 144     obj
->m_timeStamp 
= m_timeStamp
; 
 146     obj
->m_skipped 
= m_skipped
; 
 147     obj
->m_callbackUserData 
= m_callbackUserData
; 
 148     obj
->m_isCommandEvent 
= m_isCommandEvent
; 
 158 wxCommandEvent::wxCommandEvent(wxEventType commandType
, int theId
) 
 160     m_eventType 
= commandType
; 
 161     m_clientData 
= (char *) NULL
; 
 162     m_clientObject 
= (wxClientData 
*) NULL
; 
 166     m_commandString 
= wxEmptyString
; 
 167     m_isCommandEvent 
= TRUE
; 
 170 void wxCommandEvent::CopyObject(wxObject
& obj_d
) const 
 172     wxCommandEvent 
*obj 
= (wxCommandEvent 
*)&obj_d
; 
 174     wxEvent::CopyObject(obj_d
); 
 176     obj
->m_clientData    
= m_clientData
; 
 177     obj
->m_clientObject  
= m_clientObject
; 
 178     obj
->m_extraLong     
= m_extraLong
; 
 179     obj
->m_commandInt    
= m_commandInt
; 
 180     obj
->m_commandString 
= m_commandString
; 
 187 void wxNotifyEvent::CopyObject(wxObject
& obj_d
) const 
 189     wxNotifyEvent 
*obj 
= (wxNotifyEvent 
*)&obj_d
; 
 191     wxEvent::CopyObject(obj_d
); 
 193     if (!m_bAllow
) obj
->Veto(); 
 200 wxScrollEvent::wxScrollEvent(wxEventType commandType
, 
 204              : wxCommandEvent(commandType
, id
) 
 206     m_extraLong 
= orient
; 
 214 wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType
, 
 218     m_eventType 
= commandType
; 
 219     m_extraLong 
= orient
; 
 223 void wxScrollWinEvent::CopyObject(wxObject
& obj_d
) const 
 225     wxScrollWinEvent 
*obj 
= (wxScrollWinEvent
*)&obj_d
; 
 227     wxEvent::CopyObject(obj_d
); 
 229     obj
->m_extraLong    
= m_extraLong
; 
 230     obj
->m_commandInt   
= m_commandInt
; 
 238 wxMouseEvent::wxMouseEvent(wxEventType commandType
) 
 240     m_eventType 
= commandType
; 
 243     m_controlDown 
= FALSE
; 
 247     m_middleDown 
= FALSE
; 
 252 void wxMouseEvent::CopyObject(wxObject
& obj_d
) const 
 254     wxMouseEvent 
*obj 
= (wxMouseEvent 
*)&obj_d
; 
 256     wxEvent::CopyObject(obj_d
); 
 258     obj
->m_metaDown 
= m_metaDown
; 
 259     obj
->m_altDown 
= m_altDown
; 
 260     obj
->m_controlDown 
= m_controlDown
; 
 261     obj
->m_shiftDown 
= m_shiftDown
; 
 262     obj
->m_leftDown 
= m_leftDown
; 
 263     obj
->m_rightDown 
= m_rightDown
; 
 264     obj
->m_middleDown 
= m_middleDown
; 
 269 // True if was a button dclick event (1 = left, 2 = middle, 3 = right) 
 270 // or any button dclick event (but = -1) 
 271 bool wxMouseEvent::ButtonDClick(int but
) const 
 276             return (LeftDClick() || MiddleDClick() || RightDClick()); 
 280             return MiddleDClick(); 
 282             return RightDClick(); 
 284             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDClick")); 
 290 // True if was a button down event (1 = left, 2 = middle, 3 = right) 
 291 // or any button down event (but = -1) 
 292 bool wxMouseEvent::ButtonDown(int but
) const 
 297             return (LeftDown() || MiddleDown() || RightDown()); 
 305             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDown")); 
 311 // True if was a button up event (1 = left, 2 = middle, 3 = right) 
 312 // or any button up event (but = -1) 
 313 bool wxMouseEvent::ButtonUp(int but
) const 
 317             return (LeftUp() || MiddleUp() || RightUp()); 
 325             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonUp")); 
 331 // True if the given button is currently changing state 
 332 bool wxMouseEvent::Button(int but
) const 
 336             return (ButtonUp(-1) || ButtonDown(-1) || ButtonDClick(-1)); 
 338             return (LeftDown() || LeftUp() || LeftDClick()); 
 340             return (MiddleDown() || MiddleUp() || MiddleDClick()); 
 342             return (RightDown() || RightUp() || RightDClick()); 
 344             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::Button")); 
 350 bool wxMouseEvent::ButtonIsDown(int but
) const 
 354             return (LeftIsDown() || MiddleIsDown() || RightIsDown()); 
 358             return MiddleIsDown(); 
 360             return RightIsDown(); 
 362             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonIsDown")); 
 368 // Find the logical position of the event given the DC 
 369 wxPoint 
wxMouseEvent::GetLogicalPosition(const wxDC
& dc
) const 
 371     wxPoint 
pt(dc
.DeviceToLogicalX(m_x
), dc
.DeviceToLogicalY(m_y
)); 
 381 wxKeyEvent::wxKeyEvent(wxEventType type
) 
 385     m_controlDown 
= FALSE
; 
 392 void wxKeyEvent::CopyObject(wxObject
& obj_d
) const 
 394     wxKeyEvent 
*obj 
= (wxKeyEvent 
*)&obj_d
; 
 395     wxEvent::CopyObject(obj_d
); 
 399     obj
->m_keyCode 
= m_keyCode
; 
 401     obj
->m_shiftDown   
= m_shiftDown
; 
 402     obj
->m_controlDown 
= m_controlDown
; 
 403     obj
->m_metaDown    
= m_metaDown
; 
 404     obj
->m_altDown     
= m_altDown
; 
 405     obj
->m_keyCode     
= m_keyCode
; 
 413 void wxSizeEvent::CopyObject(wxObject
& obj_d
) const 
 415     wxSizeEvent 
*obj 
= (wxSizeEvent 
*)&obj_d
; 
 416     wxEvent::CopyObject(obj_d
); 
 418     obj
->m_size 
= m_size
; 
 421 void wxMoveEvent::CopyObject(wxObject
& obj_d
) const 
 423     wxMoveEvent 
*obj 
= (wxMoveEvent 
*)&obj_d
; 
 424     wxEvent::CopyObject(obj_d
); 
 429 void wxEraseEvent::CopyObject(wxObject
& obj_d
) const 
 431     wxEraseEvent 
*obj 
= (wxEraseEvent 
*)&obj_d
; 
 432     wxEvent::CopyObject(obj_d
); 
 437 void wxActivateEvent::CopyObject(wxObject
& obj_d
) const 
 439     wxActivateEvent 
*obj 
= (wxActivateEvent 
*)&obj_d
; 
 440     wxEvent::CopyObject(obj_d
); 
 442     obj
->m_active 
= m_active
; 
 445 void wxMenuEvent::CopyObject(wxObject
& obj_d
) const 
 447     wxMenuEvent 
*obj 
= (wxMenuEvent 
*)&obj_d
; 
 448     wxEvent::CopyObject(obj_d
); 
 450     obj
->m_menuId 
= m_menuId
; 
 453 void wxCloseEvent::CopyObject(wxObject
& obj_d
) const 
 455     wxCloseEvent 
*obj 
= (wxCloseEvent 
*)&obj_d
; 
 456     wxEvent::CopyObject(obj_d
); 
 458     obj
->m_loggingOff 
= m_loggingOff
; 
 459     obj
->m_veto 
= m_veto
; 
 460 #if WXWIN_COMPATIBILITY 
 461     obj
->m_force 
= m_force
; 
 463     obj
->m_canVeto 
= m_canVeto
; 
 466 void wxShowEvent::CopyObject(wxObject
& obj_d
) const 
 468     wxShowEvent 
*obj 
= (wxShowEvent 
*)&obj_d
; 
 469     wxEvent::CopyObject(obj_d
); 
 471     obj
->m_show 
= m_show
; 
 474 void wxJoystickEvent::CopyObject(wxObject
& obj_d
) const 
 476     wxJoystickEvent 
*obj 
= (wxJoystickEvent 
*)&obj_d
; 
 477     wxEvent::CopyObject(obj_d
); 
 480     obj
->m_zPosition 
= m_zPosition
; 
 481     obj
->m_buttonChange 
= m_buttonChange
; 
 482     obj
->m_buttonState 
= m_buttonState
; 
 483     obj
->m_joyStick 
= m_joyStick
; 
 486 void wxDropFilesEvent::CopyObject(wxObject
& obj_d
) const 
 488     wxDropFilesEvent 
*obj 
= (wxDropFilesEvent 
*)&obj_d
; 
 489     wxEvent::CopyObject(obj_d
); 
 491     obj
->m_noFiles 
= m_noFiles
; 
 493     // TODO: Problem with obj->m_files. It should be deallocated by the 
 494     // destructor of the event. 
 497 void wxUpdateUIEvent::CopyObject(wxObject 
&obj_d
) const 
 499     wxUpdateUIEvent 
*obj 
= (wxUpdateUIEvent 
*)&obj_d
; 
 500     wxEvent::CopyObject(obj_d
); 
 502     obj
->m_checked 
= m_checked
; 
 503     obj
->m_enabled 
= m_enabled
; 
 504     obj
->m_text 
= m_text
; 
 505     obj
->m_setText 
= m_setText
; 
 506     obj
->m_setChecked 
= m_setChecked
; 
 507     obj
->m_setEnabled 
= m_setEnabled
; 
 510 void wxPaletteChangedEvent::CopyObject(wxObject 
&obj_d
) const 
 512     wxPaletteChangedEvent 
*obj 
= (wxPaletteChangedEvent 
*)&obj_d
; 
 513     wxEvent::CopyObject(obj_d
); 
 515     obj
->m_changedWindow 
= m_changedWindow
; 
 518 void wxQueryNewPaletteEvent::CopyObject(wxObject
& obj_d
) const 
 520     wxQueryNewPaletteEvent 
*obj 
= (wxQueryNewPaletteEvent 
*)&obj_d
; 
 521     wxEvent::CopyObject(obj_d
); 
 523     obj
->m_paletteRealized 
= m_paletteRealized
; 
 526 wxWindowCreateEvent::wxWindowCreateEvent(wxWindow 
*win
) 
 529     SetEventType(wxEVT_CREATE
); 
 533 wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow 
*win
) 
 536     SetEventType(wxEVT_DESTROY
); 
 542 void wxIdleEvent::CopyObject(wxObject
& obj_d
) const 
 544     wxIdleEvent 
*obj 
= (wxIdleEvent 
*)&obj_d
; 
 545     wxEvent::CopyObject(obj_d
); 
 547     obj
->m_requestMore 
= m_requestMore
; 
 554 wxEvtHandler::wxEvtHandler() 
 556     m_nextHandler 
= (wxEvtHandler 
*) NULL
; 
 557     m_previousHandler 
= (wxEvtHandler 
*) NULL
; 
 559     m_dynamicEvents 
= (wxList 
*) NULL
; 
 561     m_pendingEvents 
= (wxList 
*) NULL
; 
 563 #  if !defined(__VISAGECPP__) 
 564     m_eventsLocker 
= new wxCriticalSection
; 
 569 wxEvtHandler::~wxEvtHandler() 
 571     // Takes itself out of the list of handlers 
 572     if (m_previousHandler
) 
 573         m_previousHandler
->m_nextHandler 
= m_nextHandler
; 
 576         m_nextHandler
->m_previousHandler 
= m_previousHandler
; 
 580         wxNode 
*node 
= m_dynamicEvents
->First(); 
 583             wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 584             if (entry
->m_callbackUserData
) delete entry
->m_callbackUserData
; 
 588         delete m_dynamicEvents
; 
 591     delete m_pendingEvents
; 
 594 #  if !defined(__VISAGECPP__) 
 595     delete m_eventsLocker
; 
 602 bool wxEvtHandler::ProcessThreadEvent(wxEvent
& event
) 
 604     // check that we are really in a child thread 
 605     wxASSERT_MSG( !wxThread::IsMain(), 
 606                   wxT("use ProcessEvent() in main thread") ); 
 608     AddPendingEvent(event
); 
 613 #endif // wxUSE_THREADS 
 615 void wxEvtHandler::AddPendingEvent(wxEvent
& event
) 
 617     // 1) Add event to list of pending events of this event handler 
 619 #if defined(__VISAGECPP__) 
 620     wxENTER_CRIT_SECT( m_eventsLocker
); 
 622     wxENTER_CRIT_SECT( *m_eventsLocker
); 
 625     if ( !m_pendingEvents 
) 
 626       m_pendingEvents 
= new wxList
; 
 628     wxEvent 
*event2 
= (wxEvent 
*)event
.Clone(); 
 630     m_pendingEvents
->Append(event2
); 
 632 #if defined(__VISAGECPP__) 
 633     wxLEAVE_CRIT_SECT( m_eventsLocker
); 
 635     wxLEAVE_CRIT_SECT( *m_eventsLocker
); 
 638     // 2) Add this event handler to list of event handlers that 
 639     //    have pending events. 
 641     wxENTER_CRIT_SECT(*wxPendingEventsLocker
); 
 643     if ( !wxPendingEvents 
) 
 644         wxPendingEvents 
= new wxList
; 
 645     wxPendingEvents
->Append(this); 
 647     wxLEAVE_CRIT_SECT(*wxPendingEventsLocker
); 
 649     // 3) Inform the system that new pending events are somwehere, 
 650     //    and that these should be processed in idle time. 
 654 void wxEvtHandler::ProcessPendingEvents() 
 656 #if defined(__VISAGECPP__) 
 657     wxENTER_CRIT_SECT( m_eventsLocker
); 
 659     wxENTER_CRIT_SECT( *m_eventsLocker
); 
 662     wxNode 
*node 
= m_pendingEvents
->First(); 
 665         wxEvent 
*event 
= (wxEvent 
*)node
->Data(); 
 668         // In ProcessEvent, new events might get added and 
 669             // we can safely leave the crtical section here. 
 670 #if defined(__VISAGECPP__) 
 671         wxLEAVE_CRIT_SECT( m_eventsLocker
); 
 673         wxLEAVE_CRIT_SECT( *m_eventsLocker
); 
 675         ProcessEvent(*event
); 
 677 #if defined(__VISAGECPP__) 
 678         wxENTER_CRIT_SECT( m_eventsLocker
); 
 680         wxENTER_CRIT_SECT( *m_eventsLocker
); 
 683         node 
= m_pendingEvents
->First(); 
 686 #if defined(__VISAGECPP__) 
 687     wxLEAVE_CRIT_SECT( m_eventsLocker
); 
 689     wxLEAVE_CRIT_SECT( *m_eventsLocker
); 
 697 bool wxEvtHandler::ProcessEvent(wxEvent
& event
) 
 700     // check that our flag corresponds to reality 
 701     wxASSERT( m_isWindow 
== IsKindOf(CLASSINFO(wxWindow
)) ); 
 704     // An event handler can be enabled or disabled 
 705     if ( GetEvtHandlerEnabled() ) 
 710         What is this? When using GUI threads, a non main 
 711         threads can send an event and process it itself. 
 712         This breaks GTK's GUI threads, so please explain. 
 715         // Check whether we are in a child thread. 
 716         if ( !wxThread::IsMain() ) 
 717           return ProcessThreadEvent(event
); 
 720         // Handle per-instance dynamic event tables first 
 721         if ( m_dynamicEvents 
&& SearchDynamicEventTable(event
) ) 
 724         // Then static per-class event tables 
 725         const wxEventTable 
*table 
= GetEventTable(); 
 727 #if wxUSE_GUI && wxUSE_VALIDATORS 
 728         // Try the associated validator first, if this is a window. 
 729         // Problem: if the event handler of the window has been replaced, 
 730         // this wxEvtHandler may no longer be a window. 
 731         // Therefore validators won't be processed if the handler 
 732         // has been replaced with SetEventHandler. 
 733         // THIS CAN BE CURED if PushEventHandler is used instead of 
 734         // SetEventHandler, and then processing will be passed down the 
 735         // chain of event handlers. 
 738             wxWindow 
*win 
= (wxWindow 
*)this; 
 740             // Can only use the validator of the window which 
 741             // is receiving the event 
 742             if ( win 
== event
.GetEventObject() ) 
 744                 wxValidator 
*validator 
= win
->GetValidator(); 
 745                 if ( validator 
&& validator
->ProcessEvent(event
) ) 
 753         // Search upwards through the inheritance hierarchy 
 756             if ( SearchEventTable((wxEventTable
&)*table
, event
) ) 
 758             table 
= table
->baseTable
; 
 762     // Try going down the event handler chain 
 763     if ( GetNextHandler() ) 
 765         if ( GetNextHandler()->ProcessEvent(event
) ) 
 770     // Carry on up the parent-child hierarchy, 
 771     // but only if event is a command event: it wouldn't 
 772     // make sense for a parent to receive a child's size event, for example 
 773     if ( m_isWindow 
&& event
.IsCommandEvent() ) 
 775         wxWindow 
*win 
= (wxWindow 
*)this; 
 776         wxWindow 
*parent 
= win
->GetParent(); 
 777         if (parent 
&& !parent
->IsBeingDeleted()) 
 778             return parent
->GetEventHandler()->ProcessEvent(event
); 
 782     // Last try - application object. 
 783     if ( wxTheApp 
&& (this != wxTheApp
) ) 
 785         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always 
 786         // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be 
 787         // processed appropriately via SearchEventTable. 
 788         if ( event
.GetEventType() != wxEVT_IDLE 
) 
 790             if ( wxTheApp
->ProcessEvent(event
) ) 
 798 bool wxEvtHandler::SearchEventTable(wxEventTable
& table
, wxEvent
& event
) 
 801     int commandId 
= event
.GetId(); 
 803     // BC++ doesn't like while (table.entries[i].m_fn) 
 806     while (table
.entries
[i
].m_fn 
!= 0) 
 808     while (table
.entries
[i
].m_fn 
!= 0L) 
 811         if ((event
.GetEventType() == table
.entries
[i
].m_eventType
) && 
 812                 (table
.entries
[i
].m_id 
== -1 || // Match, if event spec says any id will do (id == -1) 
 813                  (table
.entries
[i
].m_lastId 
== -1 && commandId 
== table
.entries
[i
].m_id
) || 
 814                  (table
.entries
[i
].m_lastId 
!= -1 && 
 815                   (commandId 
>= table
.entries
[i
].m_id 
&& commandId 
<= table
.entries
[i
].m_lastId
)))) 
 818             event
.m_callbackUserData 
= table
.entries
[i
].m_callbackUserData
; 
 820             (this->*((wxEventFunction
) (table
.entries
[i
].m_fn
)))(event
); 
 822             if ( event
.GetSkipped() ) 
 832 void wxEvtHandler::Connect( int id
, int lastId
, 
 833                             wxEventType eventType
, 
 834                             wxObjectEventFunction func
, 
 837     wxEventTableEntry 
*entry 
= new wxEventTableEntry
; 
 839     entry
->m_lastId 
= lastId
; 
 840     entry
->m_eventType 
= eventType
; 
 842     entry
->m_callbackUserData 
= userData
; 
 844     if (!m_dynamicEvents
) 
 845         m_dynamicEvents 
= new wxList
; 
 847     m_dynamicEvents
->Append( (wxObject
*) entry 
); 
 850 bool wxEvtHandler::Disconnect( int id
, int lastId
, wxEventType eventType
, 
 851                   wxObjectEventFunction func
, 
 854     if (!m_dynamicEvents
) 
 857     wxNode 
*node 
= m_dynamicEvents
->First(); 
 860         wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 861         if ((entry
->m_id 
== id
) && 
 862             ((entry
->m_lastId 
== lastId
) || (lastId 
== -1)) && 
 863             ((entry
->m_eventType 
== eventType
) || (eventType 
== wxEVT_NULL
)) && 
 864             ((entry
->m_fn 
== func
) || (func 
== (wxObjectEventFunction
)NULL
)) && 
 865             ((entry
->m_callbackUserData 
== userData
) || (userData 
== (wxObject
*)NULL
))) 
 867             if (entry
->m_callbackUserData
) delete entry
->m_callbackUserData
; 
 868             m_dynamicEvents
->DeleteNode( node 
); 
 877 bool wxEvtHandler::SearchDynamicEventTable( wxEvent
& event 
) 
 879     wxCHECK_MSG( m_dynamicEvents
, FALSE
, 
 880                  wxT("caller should check that we have dynamic events") ); 
 882     int commandId 
= event
.GetId(); 
 884     wxNode 
*node 
= m_dynamicEvents
->First(); 
 887         wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 891             // Match, if event spec says any id will do (id == -1) 
 892             if ( (event
.GetEventType() == entry
->m_eventType
) && 
 893                  (entry
->m_id 
== -1 || 
 894                   (entry
->m_lastId 
== -1 && commandId 
== entry
->m_id
) || 
 895                   (entry
->m_lastId 
!= -1 && 
 896                   (commandId 
>= entry
->m_id 
&& commandId 
<= entry
->m_lastId
))) ) 
 899                 event
.m_callbackUserData 
= entry
->m_callbackUserData
; 
 901                 (this->*((wxEventFunction
) (entry
->m_fn
)))(event
); 
 903                 if (event
.GetSkipped()) 
 914 #if WXWIN_COMPATIBILITY 
 915 bool wxEvtHandler::OnClose() 
 917     if (GetNextHandler()) 
 918         return GetNextHandler()->OnClose(); 
 922 #endif // WXWIN_COMPATIBILITY 
 926 // Find a window with the focus, that is also a descendant of the given window. 
 927 // This is used to determine the window to initially send commands to. 
 928 wxWindow
* wxFindFocusDescendant(wxWindow
* ancestor
) 
 930     // Process events starting with the window with the focus, if any. 
 931     wxWindow
* focusWin 
= wxWindow::FindFocus(); 
 932     wxWindow
* win 
= focusWin
; 
 934     // Check if this is a descendant of this frame. 
 935     // If not, win will be set to NULL. 
 941             win 
= win
->GetParent(); 
 943     if (win 
== (wxWindow
*) NULL
) 
 944         focusWin 
= (wxWindow
*) NULL
;