BEGIN_MESSAGE_MAP导致C++Builder 10.1崩溃到桌面
BEGIN_MESSAGE_MAP caused C++ Builder 10.1 to crash to desktop
我正在编写一个VCL组件TGIcon,以模拟windows桌面中的图标,它一直运行良好,直到我决定将MouseEnter和MouseLeave事件添加到组件中。我遵循了以下指南:Embarcadero Community
这是我的代码(标题(:
class PACKAGE TGIcon : public TGraphicControl
{
private:
AnsiString FCaption;
TPngImage *FIcon, *FDIcon;
TFont *FFont;
TNotifyEvent FOnMouseEnter;
TNotifyEvent FOnMouseLeave;
void __fastcall CMMouseEnter(TMessage &Message);
void __fastcall CMMouseLeave(TMessage &Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGIcon)
protected:
virtual void __fastcall Paint();
void __fastcall SetCaption(AnsiString value);
void __fastcall SetIcon(TPngImage *value);
void __fastcall SetFont(TFont *value);
public:
__fastcall TGIcon(TComponent* Owner);
__fastcall ~TGIcon();
void __fastcall MakeGray(void);
__published:
__property AnsiString Caption = {read=FCaption, write=SetCaption, nodefault};
__property TPngImage *Icon = {read=FIcon, write=SetIcon};
__property TFont *Font = {read=FFont, write=SetFont};
__property Parent;
__property Enabled;
__property OnClick;
__property TNotifyEvent OnMouseEnter = {read=FOnMouseEnter, write=FOnMouseEnter};
__property TNotifyEvent OnMouseLeave = {read=FOnMouseLeave, write=FOnMouseLeave};
};
每当我试图将组件放置在窗体上时,IDE(C++Builder Starter(都会崩溃到桌面。我已经追踪到问题的根源是"BEGIN_MESSAGE_MAP…END_MESSAGE-MAP"部分。如果我把那个部分注释掉,这个组件工作得很好。
我曾经在C++Builder XE5(Professional(中使用过相同的组件,但由于它是由一家我不再合作的公司所有,我没有该组件的二进制文件,所以我必须在这里重写它。据我记忆所及,我所做的与我在XE5中写的完全相同,那个有效,但这个会使IDE崩溃,没有错误消息,没有访问违规,只有普通CTD
有人能帮忙吗?我需要做些什么才能在C++Builder 10.1(柏林(入门版中完成这项工作吗?这是C++Builder的一个错误,还是这是Starter Edition中无法完成的,只能在"付费"版本中完成??或者这种方法已经过时了?如果是,请告诉我"现代化"的C++编译器是如何做到的。
提前谢谢。
您的MESSAGE_MAP
被错误终止。在END_MESSAGE_MAP
宏中,必须指定组件派生自的基类(TGraphicControl
(。
MESSAGE_MAP
只是覆盖虚拟Dispatch()
方法的一种奇特方式,其中:
BEGIN_MESSAGE_MAP
声明并打开重写的方法,并打开switch
语句MESSAGE_HANDLER
(如果您的项目使用ATL,请改用VCL_MESSAGE_HANDLER
(为switch
声明case
语句END_MESSAGE_MAP
为未处理的消息调用指定类的Dispatch()
方法,关闭switch
,并关闭重写的方法
以下是sysmac.h
:的声明
#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;
}
}
所以,这个代码:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGIcon) // <-- error!
由预处理器转换为此代码,这就是编译器所看到的:
virtual void __fastcall Dispatch(void *Message)
{
switch (((PMessage)Message)->Msg)
{
case CM_MOUSEENTER:
CMMouseEnter(*((TMessage *)Message));
break;
case CM_MOUSELEAVE:
CMMouseLeave(*((TMessage *)Message));
break;
default:
TGIcon::Dispatch(Message); // <-- recursive loop!
break;
}
}
正如您所看到的,由于您在END_MESSAGE_MAP
中指定自己的组件类(TGIcon
(而不是基类(TGraphicControl
(,因此当组件接收到未处理的消息时,您将创建一个无休止的递归循环。CCD_ 19再次呼叫CCD_ 20。它需要调用TGraphicControl::Dispatch()
(CMMouseEnter()
和CMMouseLeave()
方法也是如此(:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMMouseEnter)
MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMMouseLeave)
END_MESSAGE_MAP(TGraphicControl) // <-- fixed!
- 当回溯以零开始时,如何调试崩溃
- 试图在visual studio上用C++创建一个桌面应用程序
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- Windows桌面程序保存您的计算机会话 - 基于程序崩溃时的恢复会话
- BEGIN_MESSAGE_MAP导致C++Builder 10.1崩溃到桌面
- 我可以在C++桌面游戏中使用崩溃吗?
- 在我关闭刚开始的孩子对话框并进入父母对话框之后,我的QT桌面应用程序不断崩溃
- 在简单的数学操作崩溃到桌面