TForm:添加消息处理程序并调用继承
TForm: Add a message handler and call inherited
假设我需要在我的 C++ Builder cpp 文件中创建一个 Windows 消息处理程序。
我会像这样为 WM_SIZE
编写处理程序:
h 文件:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SIZE, TWMSize, OnWMSize)
END_MESSAGE_MAP(TControl)
void __fastcall OnWMSize(TWMSize &msg);
cpp 文件:
void __fastcall TForm1::OnWMSize(TWMSize &msg)
{
if (msg.SizeType == SIZE_MAXIMIZED)
Caption = "Maximized";
// This is a Delphi call and won't work in C++:
// inherited;
// Cpp call. Won't compile due to method visibility (private)
// TForm::WMSize(msg);
// Cpp call. Compiles but doesn't get expected behavior
DefaultHandler((void*)&msg);
}
如示例所示,使用 Delphi 这非常简单,只需调用 inherited
.
但是使用 C++,我如何在 C++ Builder 中调用基 class? WMSize
方法在 TScrollingWinControl
中声明为私有方法。
在此示例中,不调用基 class 会破坏 Anchors
功能。使用 DefaultHandler
也不能解决问题。
我是不是遗漏了什么明显的东西?
首先,您将错误的 class 类型传递给了 END_MESSAGE_MAP()
。您需要指定 直系父级 class,在本例中为 TForm
,而不是 TControl
:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SIZE, TWMSize, OnWMSize)
END_MESSAGE_MAP(TForm) // <-- here
现在,话虽如此,MESSAGE_MAP
只是一种覆盖虚拟 Dispatch()
方法的奇特方式:
#define BEGIN_MESSAGE_MAP virtual void __fastcall Dispatch(void *Message) \
{ \
switch (((PMessage)Message)->Msg) \
{
#define VCL_MESSAGE_HANDLER(msg,type,meth) \
case msg: \
meth(*((type *)Message)); \
break;
// NOTE: ATL defines a MESSAGE_HANDLER macro which conflicts with VCL's macro. The
// VCL macro has been renamed to VCL_MESSAGE_HANDLER. If you are not using ATL,
// MESSAGE_HANDLER is defined as in previous versions of BCB.
//
#if !defined(USING_ATL) && !defined(USING_ATLVCL) && !defined(INC_ATL_HEADERS)
#define MESSAGE_HANDLER VCL_MESSAGE_HANDLER
#endif // ATL_COMPAT
#define END_MESSAGE_MAP(base) default: \
base::Dispatch(Message); \
break; \
} \
}
因此,您的 MESSAGE_MAP
解析为以下代码逻辑:
virtual void __fastcall Dispatch(void *Message)
{
switch (((PMessage)Message)->Msg)
{
case WM_SIZE:
OnWMSize(*((TWMSize *)Message));
break;
default:
TForm::Dispatch(Message);
break;
}
}
如您所见,END_MESSAGE_MAP()
只是将未处理的消息传递给基本 class TForm::Dispatch()
方法。您必须在消息处理程序中执行相同的操作,例如:
void __fastcall TForm1::OnWMSize(TWMSize &msg)
{
if (msg.SizeType == SIZE_MAXIMIZED)
Caption = "Maximized";
TForm::Dispatch(&msg);
}
假设我需要在我的 C++ Builder cpp 文件中创建一个 Windows 消息处理程序。
我会像这样为 WM_SIZE
编写处理程序:
h 文件:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SIZE, TWMSize, OnWMSize)
END_MESSAGE_MAP(TControl)
void __fastcall OnWMSize(TWMSize &msg);
cpp 文件:
void __fastcall TForm1::OnWMSize(TWMSize &msg)
{
if (msg.SizeType == SIZE_MAXIMIZED)
Caption = "Maximized";
// This is a Delphi call and won't work in C++:
// inherited;
// Cpp call. Won't compile due to method visibility (private)
// TForm::WMSize(msg);
// Cpp call. Compiles but doesn't get expected behavior
DefaultHandler((void*)&msg);
}
如示例所示,使用 Delphi 这非常简单,只需调用 inherited
.
但是使用 C++,我如何在 C++ Builder 中调用基 class? WMSize
方法在 TScrollingWinControl
中声明为私有方法。
在此示例中,不调用基 class 会破坏 Anchors
功能。使用 DefaultHandler
也不能解决问题。
我是不是遗漏了什么明显的东西?
首先,您将错误的 class 类型传递给了 END_MESSAGE_MAP()
。您需要指定 直系父级 class,在本例中为 TForm
,而不是 TControl
:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SIZE, TWMSize, OnWMSize)
END_MESSAGE_MAP(TForm) // <-- here
现在,话虽如此,MESSAGE_MAP
只是一种覆盖虚拟 Dispatch()
方法的奇特方式:
#define BEGIN_MESSAGE_MAP virtual void __fastcall Dispatch(void *Message) \
{ \
switch (((PMessage)Message)->Msg) \
{
#define VCL_MESSAGE_HANDLER(msg,type,meth) \
case msg: \
meth(*((type *)Message)); \
break;
// NOTE: ATL defines a MESSAGE_HANDLER macro which conflicts with VCL's macro. The
// VCL macro has been renamed to VCL_MESSAGE_HANDLER. If you are not using ATL,
// MESSAGE_HANDLER is defined as in previous versions of BCB.
//
#if !defined(USING_ATL) && !defined(USING_ATLVCL) && !defined(INC_ATL_HEADERS)
#define MESSAGE_HANDLER VCL_MESSAGE_HANDLER
#endif // ATL_COMPAT
#define END_MESSAGE_MAP(base) default: \
base::Dispatch(Message); \
break; \
} \
}
因此,您的 MESSAGE_MAP
解析为以下代码逻辑:
virtual void __fastcall Dispatch(void *Message)
{
switch (((PMessage)Message)->Msg)
{
case WM_SIZE:
OnWMSize(*((TWMSize *)Message));
break;
default:
TForm::Dispatch(Message);
break;
}
}
如您所见,END_MESSAGE_MAP()
只是将未处理的消息传递给基本 class TForm::Dispatch()
方法。您必须在消息处理程序中执行相同的操作,例如:
void __fastcall TForm1::OnWMSize(TWMSize &msg)
{
if (msg.SizeType == SIZE_MAXIMIZED)
Caption = "Maximized";
TForm::Dispatch(&msg);
}