C++GUI之wxWidgets(14)-编写应用涉及的类和方法(9)-事件处理(8)
迪丽瓦拉
2024-05-11 22:47:00
0

目录

    • 跳过事件
    • 可插入事件处理程序
    • 动态事件处理
    • 窗口标识符
    • 自定义事件

跳过事件

wxWidgets事件处理系统实现了与普通C++中的虚拟方法,这意味着可以更改通过重写类的事件处理函数来实现类的行为。
在许多情况下,这甚至适用于更改本机控件的行为。
例如,它是可以过滤掉系统发送给本机的选定击键事件通过重写wxTextCtrl并为键事件定义处理程序,实现文本控件使用EVT_KEY_DOWN。这可能不是所希望的,这确实会阻止发送任何关键事件。
在这种情况下事件处理程序函数必须调用wxEvent::Skip以指示搜索事件处理程序应该继续。
对于C++虚拟函数,您应该调用Skip事件对象。

例如,要使派生文本控件只接受“a”到“z”

“A”到“Z”,我们将使用以下代码:

void MyTextCtrl::OnChar(wxKeyEvent& event)
{
if ( wxIsalpha( event.KeyCode() ) )
{
// Keycode is within range, so do normal processing.
event.Skip();
}
else
{
// Illegal keystroke. We don’t call event.Skip() so the
// event is not processed anywhere else.
wxBell();
} }

可插入事件处理程序

可以从wxEvtHandler派生一个新类,定义然后调wxWindow::PushEventHandler将此对象添加到窗口的事件处理程序堆栈中。
新的事件处理程序将首先捕获事件;如果未处理它们,则将搜索堆栈中的下一个事件处理程序,依此类推。
使用wxWindow::PopEventHandler将最顶层的事件处理程序从堆栈中弹出,如果希望将其删除,则传递true。

如果需要手动调用窗口的事件处理程序,使用GetEvent检索窗口最顶层事件处理程序的处理程序函数,并使用该函数调用成员函数以确保正确处理事件处理程序堆栈。
PushEventHandler的一个用途是临时或永久更改GUI的行为。太

动态事件处理

在运行时指定事件及其处理程序之间的映射。在不同的位置使用不同的事件处理程序事件处理程序允许更大的粒度,您可以在运行时打开和关闭单个事件处理程序,而PushEventHandler和PopEventHandler处理整个事件表。此外,它们允许在不同对象之间共享事件处理程序函数。

有两个与动态事件表相关的函数:wxEvtHandler::Connect和wxEvtEvtHandler:::Disconnect。通常,不需要调用wxEvtHandler::Disconnect,因为断开连接将在窗口对象被破坏时发生。

frame->Connect( wxID_EXIT,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler(MyFrame::OnQuit) );
frame->Connect( wxID_ABOUT,wxEVT_COMMAND_MENU_SELECTED,wxCommandEventHandler(MyFrame::OnAbout) );

事件标识符(wxEVT_COMMAND_MENU_SELECTED)与事件表宏不同
(EVT_MENU)

xCommandEventHandler宏是要编译器强制转换所必需的。如果有一个处理程序接受名为wxXYZEvent的事件,那么在Connect调用中,将在宏wxXYZEventHandler中包装函数名。

删除事件和处理程序函数之间的映射:

frame->Disconnect( wxID_EXIT,
wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(MyFrame::OnQuit) );frame->Disconnect( wxID_ABOUT,
wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventFunction(MyFrame::OnAbout) );

窗口标识符

窗口标识符是整数,用于唯一确定窗口事件系统中的标识。
事实上,标识符仅在特定上下文中是唯一可以了,例如框架及其子对象。
将wxID_ANY传递给窗口构造函数,wxWidget将自动为您生成标识符。
这在你不在乎确切的标识符,在这种情况下,应该在事件中指定wxID_ANY,
生成的标识符始终是负的,因此它们不会与用户指定的标识符冲突,用户指定的标识必须始终为正。

自定义事件

如果要定义自己的事件类和宏,需要执行以下步骤:

1、从合适的类派生类,声明动态类型信息并包含克隆函数,可能需要也可能不需要添加数据成员和访问者。
如果需要事件,则从wxCommandEvent派生
如果还希望处理程序能够调用Veto,则从wxNotifyEvent派生。
2、为事件处理程序函数定义typedef。

3、为事件类支持的各个事件定义一个事件类型表。
事件表在头文件中使用BEGIN_DECLARE_event_TYPES()…END_DECLARE_EVENT_TYPES()
每个类型都用DECLARE_EVENT_TABLE(name, integer).声明。
然后在实现文件中,写入DEFINE_EVENT_TYPE(name,)。

4、为每个事件类型定义一个事件表宏。

例子
新控件类wxFontSelectorCtrl,显示字体预览
定义一个新的事件类wxFontSelectorCtrlEvent。应用程序将能够将字体更改事件路由到事件处理程序宏EVT_FONT_SELECTION_CHANGED(id,func),它使用单个事件键入wxEVT_COMMAND_FONT_SELECTION_CHANGED。

/*!
* Font selector event class
*/
class wxFontSelectorCtrlEvent : public wxNotifyEvent
{
public:
wxFontSelectorCtrlEvent(wxEventType commandType = wxEVT_NULL,
int id = 0): wxNotifyEvent(commandType, id)
{}
wxFontSelectorCtrlEvent(const wxFontSelectorCtrlEvent& event):
wxNotifyEvent(event)
{}
virtual wxEvent *Clone() const
{ return new wxFontSelectorCtrlEvent(*this); }
DECLARE_DYNAMIC_CLASS(wxFontSelectorCtrlEvent);
};
typedef void (wxEvtHandler::*wxFontSelectorCtrlEventFunction)
(wxFontSelectorCtrlEvent&);
/*!
* Font selector control events and macros for handling them
*/
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE(wxEVT_COMMAND_FONT_SELECTION_CHANGED, 801)
END_DECLARE_EVENT_TYPES()
#define EVT_FONT_SELECTION_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(
wxEVT_COMMAND_FONT_SELECTION_CHANGED, id, -1, (wxObjectEventFunction)
(wxEventFunction) (wxFontSelectorCtrlEventFunction) & fn,
(wxObject *) NULL ),

执行文件加入如下

DEFINE_EVENT_TYPE(wxEVT_COMMAND_FONT_SELECTION_CHANGED)
IMPLEMENT_DYNAMIC_CLASS(wxFontSelectorCtrlEvent, wxNotifyEvent)

当从鼠标处理代码中检测到选择时,字体选择器控件可以调用ProcessEvent:

wxFontSelectorCtrlEvent event(
wxEVT_COMMAND_FONT_SELECTION_CHANGED, GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);

程序的字体选择器

BEGIN_EVENT_TABLE(MyDialog, wxDialog)
EVT_FONT_SELECTION_CHANGED(ID_FONTSEL, MyDialog::OnChangeFont)
END_EVENT_TABLE()
void MyDialog::OnChangeFont(wxFontSelectorCtrlEvent& event)
{
// Take appropriate action when the font selection changed
...
}

事件宏定义:

#define EVT_FONT_SELECTION_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(
wxEVT_COMMAND_FONT_SELECTION_CHANGED, id, -1, (wxObjectEventFunction)
(wxEventFunction) (wxFontSelectorCtrlEventFunction) & fn,
(wxObject *) NULL ),

宏事件表中的五个条目

  • 事件类型。一个事件类可以处理多种类型,只定义了一种事件类型,因此只有一种事件表宏。此类型必须与事件的类型相匹配已处理以调用事件处理程序。
  • 传递给宏的标识符值。只有当表中的值与正在处理的事件中的值匹配时,才会调用事件处理程序函数。
  • 第二个标识符值,用于指定值范围-1表示没有第二个值。
  • 事件处理程序函数。某些编译器需要强制转换序列,这就是使用成员函数typedef的地方。 -
  • 用户数据,通常为NULL。

相关内容