wxWidgets事件表是什么样的C++语句
What kind of C++ statement(s) is the wxWidgets event table?
我刚开始学习wxWidgets,我遇到了一组代码行,看起来像这样:
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
wxWidgets称之为"事件表"。我想知道这是什么样的语句,因为我已经学习了一些C++教程,但我还没有见过这样的东西。它们看起来像函数调用,但没有分号。我知道这与MACROS有关,但我真的不明白这是怎么回事。这种说法是MACROS的一种说法,还是我在C++中还没有遇到的一种通用说法?
-
你是对的。
wxBEGIN_EVENT_TABLE
是"宏"的一个例子: -
那么什么是"宏"呢?这里有一个合理的定义:
https://gcc.gnu.org/onlinedocs/cpp/Macros.html
宏是被赋予名称的代码片段。无论何时使用名称时,它将被宏的内容所替换。那里是两种宏。他们的不同之处主要在于长相当它们被使用时。当使用时,类似函数的宏类似于函数调用。
- 在这种情况下,wxBEGIN_EVENT_TABLE与wxEND_EVENT_ABLE一起"扩展"到wx"事件处理程序"列表:
https://docs.wxwidgets.org/3.0/group__group__funcmacro__events.html#
#define wxBEGIN_EVENT_TABLE ( theClass, baseClass )
在源文件中使用此宏可以开始列出静态事件处理程序针对特定类别。
使用wxEND_EVENT_ABLE()终止事件声明块。
-
"宏"是在最早的汇编语言中引入的。他们只是做"文本替换"——修改实际编译器看到的源代码。
宏(和宏预处理器)是原始"C"语言的一个组成部分,并被移植到C++(和许多其他高级语言)中。
你可以在这里阅读更多关于C/C++宏的信息:
https://www.programiz.com/c-programming/c-preprocessor-macros
'希望这能帮助
事件表通常是某种类型的struct
,它包含事件消息标识符以及指向处理事件消息的函数的指针。
这种类型的数据结构在许多GUI框架中非常常用。例如,Microsoft MFC框架使用它。
事件表是实际的数据结构,不是C++编程语言的一部分。您可以使用C++来定义事件表。
使这种方法发挥作用所需的一些部分是:
-
允许搜索消息标识符以找到其关联处理程序的表结构
-
框架找到事件表的一种方法,以便使用它进行消息标识符查找,并使用正确的接口调用正确的函数
-
一种知道事件表中第一个和最后一个条目的方法
手工编码的框架表元素的简单版本可能如下所示。这将是一个用于创建事件表元素数组的元素,每个事件消息标识符一个。
typedef struct {
int msgId; // the identifier for the message type
void (*handler)(int msgId, void *msgData); // function pointer to handler
} SimpleEventTable;
在没有宏的源代码中使用这一点的一个不完整的例子如下。在本例中,MSG_ID_ONE和MSG_ID_TWO由int
值定义,而handler1
和handler2
是处理这些消息的函数:
void handler1 (int msgId, void *msgData)
{
// do things with the data associated with message identifier MSG_ID_ONE
}
void handler2 (int msgId, void *msgData)
{
// do things with the data associated with message identifier MSG_ID_TWO
}
SimpleEventTable myTable[] = {
{MSG_ID_ONE, handler1},
{MSG_ID_TWO, handler2},
{0, NULL}
};
然后,框架使用事件表来确定代码是否正在处理特定的消息标识符,以及应用程序是否正在处理消息标识符,调用什么函数来处理它。框架将提供一个默认的处理程序,在许多情况下,它只会指示消息已被处理。
大多数框架都希望更容易地完成相当于样板源代码的工作,因此会提供一组预处理器宏,使事件表更容易创建。
MFC的示例宏
我无法访问wxWidgets,但是Microsoft MFC框架提供了类似于wxWidget框架的东西,尽管MFC中填充的内容比窗口管理多得多。
使用MFC的事件表如下所示,它实际上与您正在使用的框架非常相似。此消息映射是MFC窗口类的实现文件的一部分。在这种情况下,应用程序类CFrameworkWndDoc
是从MFC类CWindowDocument
派生的,该MFC类是MFC框架的一部分。
BEGIN_MESSAGE_MAP(CFrameworkWndDoc, CWindowDocument)
ON_WM_CHAR()
ON_WM_TIMER()
ON_MESSAGE(WU_EVS_DFLT_LOAD, OnDefaultWinLoad)
ON_MESSAGE(WM_APP_SHOW_HIDE_GROUP, OnShowHideGroupMsgRcvd)
END_MESSAGE_MAP()
除了实现源文件.c文件中的上述消息映射外,类定义中还使用了DECLARE_MESSAGE_MAP()
定义,通常位于头文件中,因此类和消息映射之间存在链接。
DECLARE_MESSAGE_MAP()
宏只是将必要的声明放入类定义中,这些声明将实现文件中的实际消息映射与类联系起来。
#define DECLARE_MESSAGE_MAP()
protected:
static const AFX_MSGMAP* PASCAL GetThisMessageMap();
virtual const AFX_MSGMAP* GetMessageMap() const;
MFC包含文件具有如下定义。首先是事件表的开始和结束的两个定义,或者MFC所称的消息映射。正如您所看到的,这将创建MFC类的一个新成员,该成员由MFC框架调用,以便在MFC框架处理消息时访问消息映射。class
定义中的DECLARE_MESSAGE_MAP()
宏声明由以下宏生成的函数。
#define BEGIN_MESSAGE_MAP(theClass, baseClass)
PTM_WARNING_DISABLE
const AFX_MSGMAP* theClass::GetMessageMap() const
{ return GetThisMessageMap(); }
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap()
{
typedef theClass ThisClass;
typedef baseClass TheBaseClass;
static const AFX_MSGMAP_ENTRY _messageEntries[] =
{
#define END_MESSAGE_MAP()
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
};
static const AFX_MSGMAP messageMap =
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] };
return &messageMap;
}
PTM_WARNING_RESTORE
还有许多宏用于简化事件表的构建。MFC使用的这些比上面的简单示例复杂得多,因为它们被设计为与MFC窗口类一起使用,并被插入到源代码文件中,并由Visual Studio开发环境管理。
还要注意,MFC消息映射技术使用一组特殊标识符AfxSig_vwww
和AfxSig_lwl
,它们分别"告诉"MFC框架处理程序函数的接口应该是什么,(UINT, UINT, UINT)
和(WPARAM, LPARAM)
。
#define ON_WM_CHAR()
{ WM_CHAR, 0, 0, 0, AfxSig_vwww,
(AFX_PMSG)(AFX_PMSGW)
(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, UINT, UINT) > ( &ThisClass :: OnChar)) },
#define ON_MESSAGE(message, memberFxn)
{ message, 0, 0, 0, AfxSig_lwl,
(AFX_PMSG)(AFX_PMSGW)
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) >
(memberFxn)) },
- 我的简单if-else语句是如何无法访问的代码
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- 为什么是0;C++中的有效语句
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 我似乎对if/else的基本语句有问题:/
- 当调用switch语句中的函数时(即使函数不包含循环),似乎是永不结束的循环的问题
- If语句在c++中被忽略
- 比较if语句中的数组值和int值
- 以在Qt中的IF语句中设置时间延迟
- Craps游戏问题,忽略if语句
- "类模板示例<int>;"语句对 C++11 是什么意思?
- 如何编写一个使用n倍三元条件语句的C++布尔函数
- c++:定义if语句中的模板
- 主线的等价语句是什么