TForm:添加消息处理程序并调用inherited

时间:2017-12-26 17:33:41

标签: c++builder

假设我需要在C ++ Builder cpp文件中创建一个Windows消息处理程序。

我会为WM_SIZE写一个像这样的处理程序:

h file:

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中调用基类? WMSize方法在TScrollingWinControl中声明为私有。

在此示例中,不调用基类会破坏Anchors功能。使用DefaultHandler也无法解决问题。

我错过了一些明显的东西吗?

1 个答案:

答案 0 :(得分:1)

首先,您将错误的类类型传递给END_MESSAGE_MAP()。您需要指定直接父类,在本例中为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()只是将未处理的消息传递给基类TForm::Dispatch()方法。您必须在消息处理程序中执行相同的操作,例如:

void __fastcall TForm1::OnWMSize(TWMSize &msg)
{
    if (msg.SizeType == SIZE_MAXIMIZED)
        Caption = "Maximized";

    TForm::Dispatch(&msg);
}