目录
ProcessEvent()
virtual bool wxEvtHandler::ProcessEvent (wxEvent & event)
处理事件,搜索事件表并调用零个或多个合适的事件处理函数。
通常,您的应用程序不会调用此函数:它是在wxWidgets实现中调用的,用于将传入的用户界面事件分派给框架(和应用程序)。
但是,如果您在实现新功能(如新控件)时需要定义新的事件类型,而不是允许用户重写虚函数,那么您可能需要调用它。
请注意,您通常不需要重写ProcessEvent()来自定义事件处理,重写特别提供的TryBefore()和TryAfter()函数通常就足够了。例如,wxMDIParentFrame可以重写TryBefore()以确保在父框架本身处理之前,菜单事件在活动的子框架中被处理。
事件表搜索的正常顺序如下:
1.调用wxApp::FilterEvent()。如果它返回的不是-1(默认值),则处理在此处停止。
2.调用TryBefore()(这是考虑wxValidator对wxWindow对象影响的地方)。如果此函数返回true,则函数退出。
3.如果对象被禁用(通过调用wxEvtHandler::SetEvtHandlerEnabled),则函数跳至步骤(7)。
4.按从最近绑定到最早绑定的顺序搜索使用Bind<>()绑定的处理程序的动态事件表。如果找到处理程序,则执行它,并且除非处理程序使用wxEvent::Skip()指示它未处理该事件(在这种情况下搜索继续),否则函数返回true。
5.在源代码中,按照事件表宏出现的顺序,搜索使用事件表宏绑定的处理程序的静态事件表以查找此事件处理程序。如果失败,则尝试基类事件表,依此类推,直到没有更多表或找到合适的函数为止。如果找到处理程序,则应用与前面步骤相同的逻辑。
6.搜索应用于整个事件处理程序链(通常链的长度为1)。此链可以使用wxEvtHandler::SetNextHandler()形成:
(参考图像,如果A->ProcessEvent被调用且未处理该事件,则会调用B->ProcessEvent,依此类推...)。请注意,在wxWindow的情况下,您可以构建事件处理程序的堆栈(有关更多信息,请参阅wxWindow::PushEventHandler())。如果链中的任何处理程序返回true,则函数退出。
7.调用TryAfter():对于wxWindow对象,这可能会将事件递归地传播到窗口父级。如果事件仍未被处理,则作为最后一步,将调用wxTheApp对象上的ProcessEvent()。
请注意,步骤(2)至(6)在ProcessEventLocally()中执行,该函数由本函数调用。
参数
event 要处理的事件。
返回值
如果找到并执行了合适的事件处理程序函数,且该函数没有调用wxEvent::Skip,则返回true。
在wxWindow中重新实现。
QueueEvent()
virtual bool wxEvtHandler::QueueEvent (wxEvent * event)
将事件排队以便稍后处理。
这个方法类似于 ProcessEvent(),但后者是同步的,即事件在函数返回之前立即被处理,而这个方法是异步的,它会立即返回,事件将在稍后的某个时间(通常是在下一个事件循环迭代期间)被处理。
另一个重要的区别是,这个方法拥有对事件参数的所有权,即它自己会删除它。这意味着事件应该在堆上分配,且函数返回后,指针不能再被使用(因为它可能随时被删除)。
QueueEvent() 可以用于工作线程与主线程之间的线程间通信,它在内部使用锁定,是安全的,可以避免在 AddPendingEvent() 文档中提到的问题,确保事件对象不再被调用线程使用。然而,仍需注意避免使用此对象的某些字段,特别是事件对象的任何 wxString 成员都不应该是另一个 wxString 对象的浅拷贝,因为这会导致它们仍然在后台使用相同的字符串缓冲区。例如:
void FunctionInAWorkerThread(const wxString& str)
{
wxCommandEvent* evt = new wxCommandEvent;// NOT evt->SetString(str) 因为这将是浅拷贝
evt->SetString(str.c_str()); // 进行深拷贝wxTheApp->QueueEvent( evt );
}
注意,您可以使用 wxThreadEvent 而不是 wxCommandEvent 来避免这个问题:
void FunctionInAWorkerThread(const wxString& str)
{
wxThreadEvent evt;
evt.SetString(str);// wxThreadEvent::Clone() 确保内部的 wxString
// 成员不会被其他 wxString 实例共享:
wxTheApp->QueueEvent( evt.Clone() );
}
最后请注意,此方法通过调用wxWakeUpIdle()自动唤醒空闲的事件循环,因此在使用此方法时无需手动执行。
函数加入版本
自2.9.0版起
参数
event 要排队的堆分配事件,QueueEvent()将拥有它。此参数不应为NULL。
在wxWindow中重新实现。
// END