MFC 如何添加自定义消息
2个回答
展开全部
这是由于此类消息的处理机制决定的,这类消息没有命令消息那条繁琐的流动路径,而是消息发出者直接发给对应 CWnd的窗体句柄,由CWnd负责消息的响应。所以这类消息必须同一个CWnd类对应,更精确的说必须与一个HWND类型的窗体句柄相对应。这样得出一个重要的结论,就是从CCmdTarget中派生而没有从CWnd派生的类没有处理此类消息的能力。 综上所述,就是为什么命令消息可以放到大部分类中处理,包括CWinThread、CWinApp、CDocument、CView、CFrameWnd或是自定义的类中,而普通Windows消息和用户自定义的消息只能放到CFrameWnd和CView等派生与CWnd中的类中处理。 由此可见,我们自定义的类要想响应自定义消息就只能从CWnd中派生(当然不响应任何消息的类可以从CObject中派生)。先来看看如何自定义消息:在.h中做的工作:第一步要声明消息:#define WM_MYMSG WM_USER+8第二步要在类声明中声明消息映射:DECLARE_MESSAGE_MAP()第三步要在类声明中定义消息处理函数:afx_msg LRESULT MyMsgHandler(WPARAM,LPARAM);在.cpp中做的工作:第四步要实现消息映射:BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)END_MESSAGE_MAP()第五步要实现消息处理函数(当然可以不实现):LRESULT CMainFrame::OnMyMsgHandler(WPARAM w,LPARAM l){AfxMessageBox("Hello,World!");return 0;}在引发或发出消息的地方只用写上:::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);到此,自定义消息完毕,这是好多网上文章都写的东西。大家会发现上面代码是在CMainFrame类中实现的,但是如果要用自定义类,就没有那么简单了。显然把第四步与第五步的CMainFrame换成自定义的类名(这里我用CMyTestObject来代表自定义类)是不能正常工作的。原因在于在发送消息的SendMessage函数中的第一个参数是要响应消息对应的HWND类型的窗体句柄,而CMyTestObject类中的m_hWnd中在没有调用CWnd::Create之前是没有任何意义的,也就是没有调用CWnd::Create或CWnd::CreateEx函数时,CWnd不对应任何窗体,消息处理不能正常运作。所以,又一个重要的结论,在自定义类能够处理任何消息之前一定要确保m_hWnd关联到一个窗体,即便这个窗体是不可见的。那么有人说,在自定义类的构造函数中调用Create函数就行了,不错,当然也可以在别处调用,只要确保在消息发送之前。但是,Create的调用很有说法,要注意两个地方,第一个参数是类的名称,我建议最好设为NULL;第五个参数是父窗体对象的指针,这个函数指定的对象一定要存在,我建议最好为整个程序的主窗体。如下是我的自定义类的构造函数:CMyTestObject::CMyTestObject(){CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),::AfxGetMainWnd(),1234);} //一定要在生成主窗体后使用,在主窗体完成OnCreate消息的处理后CMyTestObject::CMyTestObject(CWnd *pParent){CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),pParent,1234);}不能如下调用Create,因为此时CMyTestObject不关联任何窗体,所以this中的m_hWnd无效:CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),this,1234);这时上面四、五两步修改成:BEGIN_MESSAGE_MAP(CMyTestObject, CWnd)ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)END_MESSAGE_MAP()LRESULT CMyTestObject::OnMyMsgHandler(WPARAM w,LPARAM l){AfxMessageBox("My Messge Handler in My Self-Custom Class!");return 0;}在类外部发出消息:CMyTestObject *test=new CMyTestObject();::SendMessage(test->m_hWnd,WM_MYMSG,0,0);在类内部某个成员函数(方法)中发出消息:::SendMessage(m_hWnd,WM_MYMSG,0,0);最后一个问题便是容易产生警告错误的窗体回收,自定义的类要显式调用窗体销毁,析构函数如下:CMyTestObject::~CMyTestObject(){CWnd::DestroyWindow();}图解VC添加自定义消息 MFC激活自定义消息
网易云信
2023-12-06 广告
2023-12-06 广告
各种消息提醒、在线状态、消息里面发礼物打电话都可以实现的。网易云信 1 对 1 UIKit 组件深入娱乐社交领域,提供一站式的产品方案,助力开发者更好、更快地构建 1 对 1 社交平台。此外,我们也提供基于底层 SDK 集成方案,使业务能够...
点击进入详情页
本回答由网易云信提供
推荐于2017-09-10 · 知道合伙人软件行家
关注
展开全部
1 发送消息
首先在A的头文件中定义这个消息:
[cpp] view plaincopy
#define WM_USERMESSAGE WM_USER+100
所有自定义消息都是以WM_USER消息为基础加上一个任意的自然数来表示的。
2 接受消息
对象接受一个消息,应该有三部分:在头文件中有该消息的处理函数的原型;在实现文件中有接受消息映射的宏;以及该消息的处理函数的具体实现。
2.1 头文件中加上自定义消息的处理函数原型
在DECLARE_MESSAGE_MAP()语句之前,一对AFX_MSG之间加上如下形式的函数原型:
afx_msg LRESULT OnProcName( WPARAM wParam, LPARAM lParam);
对Win32来说,wParam, lParam是传递消息最常用的手段。
2.2 在实现文件中加上接受消息映射的宏
在cpp文件里,BEGIN_MESSAGE_MAP语句之后,在一对BEGIN_MESSAGE_MAP(ThisClass, BaseClass)与END_MESSAGE_MAP()之间,增加 如下形式的代码:
[cpp] view plaincopy
ON_MESSAGE(WM_USERMESSAGE, OnProcName)
或
[cpp] view plaincopy
ON_THREAD_MESSAGE(WM_USERMESSAGE, OnProcName)
上面是不用分号结尾的。
2.3 在实现文件中给出消息处理函数的具体实现。
首先在A的头文件中定义这个消息:
[cpp] view plaincopy
#define WM_USERMESSAGE WM_USER+100
所有自定义消息都是以WM_USER消息为基础加上一个任意的自然数来表示的。
2 接受消息
对象接受一个消息,应该有三部分:在头文件中有该消息的处理函数的原型;在实现文件中有接受消息映射的宏;以及该消息的处理函数的具体实现。
2.1 头文件中加上自定义消息的处理函数原型
在DECLARE_MESSAGE_MAP()语句之前,一对AFX_MSG之间加上如下形式的函数原型:
afx_msg LRESULT OnProcName( WPARAM wParam, LPARAM lParam);
对Win32来说,wParam, lParam是传递消息最常用的手段。
2.2 在实现文件中加上接受消息映射的宏
在cpp文件里,BEGIN_MESSAGE_MAP语句之后,在一对BEGIN_MESSAGE_MAP(ThisClass, BaseClass)与END_MESSAGE_MAP()之间,增加 如下形式的代码:
[cpp] view plaincopy
ON_MESSAGE(WM_USERMESSAGE, OnProcName)
或
[cpp] view plaincopy
ON_THREAD_MESSAGE(WM_USERMESSAGE, OnProcName)
上面是不用分号结尾的。
2.3 在实现文件中给出消息处理函数的具体实现。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询