您的位置:首页 > 其它

MFC中的自定义消息

2015-04-28 16:52 204 查看
MFC中的消息类型:

普通消息:也就是以WM_开头,除了WM_COMMAND以外的消息,这类消息在WM_USER以下的是系统消息,WM_USER以上的可以由 用户自己定义

命令消息:就是WM_COMMAND,也就是一些菜单、工具栏中的消息,包括快捷键,这类消息处理的机制与其他以WM_开头的消息处理 机制不同,它具有一条层次明确的消息流动路径

1.如果一个类要响应消息,应该具备什么条件?

答:能够响应消息的类必须都从CCmdTarget类中派生,因为只有以这个类中提供了消息的框架和处理机制。

而CWnd类,CWinApp类、CDocument类、CDocTemplate类等都是CCmdTarget的派生类,即子类;而CFrameWnd类、CView类、CDialog类等都是从CWnd中派生的,其实也是CCmdTarget的子孙,所以都能够响应消息,但是响应消息的种类不太相同。

如果该类要求响应普通的Windows消息,那就要求自定义的类必须从CWnd中派生。

如果该类要求响应命令消息,那么自定义的类可以从CCmdTarget中派生

2.普通消息的处理机制是怎样的?

答:消息发出者直接发给对应CWnd的窗体句柄,由CWnd负责消息的响应。

所以这类消息必须同一个CWnd类对应,更精确的说必须与一个HWND类型的窗体句柄相对应。

CWnd类或其子类没有调用CWnd::Create或CWnd::CreateEx函数时,CWnd类不对应任何窗体,消息处理不能正常运作。

3.如何自定义MFC消息?

答:在.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);

4.以上是继承自CWnd类的自定义消息处理,如何自定义一个由CObject类派生的类来处理消息呢?

答:一个重要的结论,在自定义类能够处理任何消息之前一定要确保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();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: