C++GUI之wxWidgets(14)-编写应用涉及的类和方法(9)-事件处理(8)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

跳过事件

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处理整个事件表。此外它们允许在不同对象之间共享事件处理程序函数。

有两个与动态事件表相关的函数wxEvtHandlerConnect和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_TYPEname,。

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

例子
新控件类wxFontSelectorCtrl显示字体预览
定义一个新的事件类wxFontSelectorCtrlEvent。应用程序将能够将字体更改事件路由到事件处理程序宏EVT_FONT_SELECTION_CHANGEDidfunc它使用单个事件键入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。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++