目标 在应用程序中创建自己的窗口消息。 定义一个新的窗口消息,实际上是一个数字I D。然后,讨论在应用程序的类之间发送和 接收该窗口消息。步骤1. 创建一个新的窗口消息 使用以下方式定义一个新的消息。若想定义多个消息,只要使用W M _ U S E R的更大增量 即可。 # define WM_WZD_MESSAGE WM_USER+12. 发送一个新的窗口消息 利用SendMessage( )发送新消息: AfxGetMainWnd( )-> SendMessage (WM_WZD_MESSAGE, wParam, lParam);也可以自己定义存储在参数w P a r a m和l P a r a m中的值,二者都是D W O R D变量。 有两种方法来接收这个新窗口消息:第一种方法是增加O N _ M E S S A G E宏和消息处理函数本身到接收消息类的消息映像中;第二种方法是为此新消息创建自己的消息映像宏。第一种的好处是快而且简单,第二种方法的好处是在消息进行处理之前用户可以定制w P a r a m和l P a r a m参数。如果想在整个应用程序中使用这个消息,这一点很重要。这两种方法都不能利用C l a s s Wi z a r d所提供的便利,因为新消息并不在C l a s s Wi z a r d的列表中。3. 使用ON_MESSAGE( )接收新窗口消息 1) 使用文本编辑器,在接收消息的类中加入消息处理函数的定义。利用如下语法,并保证是在C l a s s Wi z a r d的{{ }}框架之后,以防止C l a s s Wi z a r d删去这里所做的工作。/ / { { A F X _ M S G ( C M a i n F r a m e ) / / } } A F X _ M S G afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);<<<< D E C L A R E _ M E S S A G E _ M A P ( )2) 然后,在实现文件中,添加消息映像宏到消息映像中。 BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) / / { { A F X _ M S G _ M A P ( C M a i n F r a m e ) / / } } A F X _ M S G _ M A P O N _ M E S S A G E ( W M _ W Z D _ M E S S A G E , O n M y M e s s a g e ) < < < < < E N D _ M E S S A G E _ M A P ( )3) 最后,加入消息处理函数。 L R E S U LT CMainFrame::OnWzdMessage(WPARAM wParam, LPARAM lParam) { / / p r o c e s s return 0; } 正如传送的w P a r a m和l P a r a m的值由你决定一样,该处理函数返回什么仍由你来决定。4. 创建新的消息映像宏 1) 用如下方式为新消息定义一个新的消息映像宏,理想情况下,其定义在一个包含文件中,以便可被应用程序的所有文件共享。#define ON_WZD_MESSAGE() \ {WM_WZD_MESSAGE, 0, 0, 0, AfxSig_vW, (AFX_PMSG)(AFX_PMSGW)(void \ (AFX_MSG_CALL CWnd::*)(CWnd *))&OnWzdMessage}, A f x S i g _ v W的值告诉M F C新消息带一个指向C W n d类的指针,且返回值是Vo i d类型。然后,把正常情况下的w P a r a m和l P a r a m参数转换为调用参数。A f x S i g _ v W的其他可用值,请参阅M F C子目录下A F X M S G _ . H文件。改变A f x S i g _ v W的值意味着改变这个宏定义的函数的调用参数。2) 使用文本编辑器添加新消息处理函数的定义到接收消息类中。使用以下语法并保证是在C l a s s Wi z a r d的{{ }}框架之后,以防止C l a s s Wi z a r d删去所做的工作。 / / { { A F X _ M S G ( C M a i n F r a m e ) / / } } A F X _ M S G afx_msg void OnMyMessage(CWnd *pWnd);<<<< D E C L A R E _ M E S S A G E _ M A P ( )3) 在实现文件中,加入新消息映像宏到消息映像中。 BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) / / { { A F X _ M S G _ M A P ( C M a i n F r a m e ) / / } } A F X _ M S G _ M A P O N _ W Z D _ M E S S A G E ( W M _ W Z D _ M E S S A G E , O n M y M e s s a g e ) < < < < < E N D _ M E S S A G E _ M A P ( )4) 最后,加入新消息处理函数。 void CMainFrame::OnWzdMessage(CWnd *pWnd) { / / p r o c e s s } 记住,这里传递的参数不是通常的w P a r a m和l P a r a m,而是更友好的C W n d指针。 说明 ■ 窗口消息的主要目的是窗口之间的内部消息处理,而不是处理诸如来自菜单的命令消息。 添加一个新的命令消息,则要定义一个新的命令I D,而不是使用W M _ C O M M A N D。 ■ 添加任何内容到映像中时,应避免把代码放在{{ }}框架之间。否则C l a s s Wi z a r d会把它 删去。 / / { { A F X _ M S G _ M A P ( C M a i n F r a m e ) <---- NOT HERE!!! / / } } A F X _ M S G _ M A P ON_WZD_MESSAGE() <---- HERE!!!! ■ 关于消息的详细内容参见第3章。例8有一个关于消息处理的实际例子。 CD说明 在C D上执行该工程时,单击O p t i o n s / W z d菜单命令,视图类发送一个客户窗口消息 ( W M _ W Z D _ M E S S A G E )到主框架类。
可以加入:比如你的消息 #define WM_YOURMSG WM_USER+100 如果要加入CMainFrame的消息映射,则在MainFrame.h中加入处理函数: afx_msg LRESULT OnUser(WPARAM wParam, LPARAM lParam);然后在cpp文件(MainFrame.cpp)中的消息映射中加入: BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code ! ON_WM_CREATE() //}}AFX_MSG_MAP ON_MESSAGE(YOURMSG, OnUser) END_MESSAGE_MAP()然后写OnUser的实现就行。 /////////////////////////////////////////////////////////////////// 多年的珍藏都拿出来了。
**************************************************
说明:
以下用一个自创的对话框类(MyMessageDlg)向视图类(MessageTestView)
发送自定义消息为例,说明这两种不同方法的自定义消息的
总结:
消息传递的方法一:使用ON_MESSAGE
使用ON_MESSAGE响应消息,必须配合定义消息#define WM_MY_MESSAGE (WM_USER+100)对于发送消息者-MyMessageDlg,
在其MyMessageDlg.h中,定义#define WM_MY_MESSAGE (WM_USER+100)
在其MyMessageDlg.cpp中要先添加:#include "MainFrm.h"
因为使用了CMainFrame*定义对象。
并且要有测试消息的函数:
void MyMessageDlg::OnButtonMsg()
{
// TODO: Add your control notification handler code here
CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd; //先通过获取当前框架指针
CView * active = pMF->GetActiveView();//才能获取当前视类指针
if(active != NULL) //获取了当前视类指针才能发送消息
active->PostMessage(WM_MY_MESSAGE,0,0); //使用PostMessage发送消息
}对于消息的接受者-MessageTestView,
在其MessageTestView.h中,也要定义#define WM_MY_MESSAGE (WM_USER+100)
并定义消息映射函数-OnMyMessage()
protected:
//{{AFX_MSG(CMessageTestView)
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
在其MessageTestView.cpp中,
先要声明响应消息:
BEGIN_MESSAGE_MAP(CMessageTestView, CEditView)
//{{AFX_MSG_MAP(CMessageTestView)
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
//}}AFX_MSG_MAP
再添加消息响应的函数实现:
LRESULT CMessageTestView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
MessageBox("OnMyMessage!");
return 0;
}
消息传递的方法二:使用ON_REGISTERED_MESSAGE
使用ON_REGISTERED_MESSAGE注册消息,必须配合
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");对于消息的发送者-MyMessageDlg,
在其MyMessageDlg.h中,只要
定义static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
就可以了。
在其MyMessageDlg.cpp中要先添加:#include "MainFrm.h"
因为使用了CMainFrame*定义对象。
并且要有测试消息的函数:
void MyMessageDlg::OnButtonMsg()
{
// TODO: Add your control notification handler code here
CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd; //先通过获取当前框架指针
CView * active = pMF->GetActiveView();//才能获取当前视类指针
if(active != NULL) //获取了当前视类指针才能发送消息
active->PostMessage(WM_MY_MESSAGE,0,0); //使用PostMessage发送消息
}对于消息的接收者-MessageTestView,
在其MessageTestView.h中不要定义
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
应该把这个定义放到MessageTestView.cpp中,要不会出现: redefinition
在其MessageTestView.h中只要定义消息映射函数
protected:
//{{AFX_MSG(CMessageTestView)
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
在其MessageTestView.cpp中,先定义
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
接着注册消息:
BEGIN_MESSAGE_MAP(CMessageTestView, CEditView)
//{{AFX_MSG_MAP(CMessageTestView)
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage)
//}}AFX_MSG_MAP
最后添加消息响应的函数实现:
LRESULT CMessageTestView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
MessageBox("OnMyMessage!");
return 0;
}
----------------------------------------------------------------
比较两种方法,只是略有不同。但也要小心谨慎,以免出现接收不到消息的情况。 -------------------------------------------------------------------其他注意事项:发送消息的-MyMessageDlg.cpp前也要定义
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");接受消息的-MessageTestView.cpp前也要定义
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");RegisterWindowMessage("Message")中""的内容是什么不重要,写什么都可以,单必须
发送者与接受者是一样的内容,例如:"Message"******************************************************
end
在应用程序中创建自己的窗口消息。
定义一个新的窗口消息,实际上是一个数字I D。然后,讨论在应用程序的类之间发送和
接收该窗口消息。步骤1. 创建一个新的窗口消息
使用以下方式定义一个新的消息。若想定义多个消息,只要使用W M _ U S E R的更大增量
即可。
# define WM_WZD_MESSAGE WM_USER+12. 发送一个新的窗口消息
利用SendMessage( )发送新消息:
AfxGetMainWnd( )-> SendMessage (WM_WZD_MESSAGE, wParam, lParam);也可以自己定义存储在参数w P a r a m和l P a r a m中的值,二者都是D W O R D变量。
有两种方法来接收这个新窗口消息:第一种方法是增加O N _ M E S S A G E宏和消息处理函数本身到接收消息类的消息映像中;第二种方法是为此新消息创建自己的消息映像宏。第一种的好处是快而且简单,第二种方法的好处是在消息进行处理之前用户可以定制w P a r a m和l P a r a m参数。如果想在整个应用程序中使用这个消息,这一点很重要。这两种方法都不能利用C l a s s Wi z a r d所提供的便利,因为新消息并不在C l a s s Wi z a r d的列表中。3. 使用ON_MESSAGE( )接收新窗口消息
1) 使用文本编辑器,在接收消息的类中加入消息处理函数的定义。利用如下语法,并保证是在C l a s s Wi z a r d的{{ }}框架之后,以防止C l a s s Wi z a r d删去这里所做的工作。/ / { { A F X _ M S G ( C M a i n F r a m e )
/ / } } A F X _ M S G
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);<<<<
D E C L A R E _ M E S S A G E _ M A P ( )2) 然后,在实现文件中,添加消息映像宏到消息映像中。
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
/ / { { A F X _ M S G _ M A P ( C M a i n F r a m e )
/ / } } A F X _ M S G _ M A P
O N _ M E S S A G E ( W M _ W Z D _ M E S S A G E , O n M y M e s s a g e ) < < < < <
E N D _ M E S S A G E _ M A P ( )3) 最后,加入消息处理函数。
L R E S U LT CMainFrame::OnWzdMessage(WPARAM wParam, LPARAM lParam)
{
/ / p r o c e s s
return 0;
}
正如传送的w P a r a m和l P a r a m的值由你决定一样,该处理函数返回什么仍由你来决定。4. 创建新的消息映像宏
1) 用如下方式为新消息定义一个新的消息映像宏,理想情况下,其定义在一个包含文件中,以便可被应用程序的所有文件共享。#define ON_WZD_MESSAGE() \
{WM_WZD_MESSAGE, 0, 0, 0, AfxSig_vW, (AFX_PMSG)(AFX_PMSGW)(void \
(AFX_MSG_CALL CWnd::*)(CWnd *))&OnWzdMessage},
A f x S i g _ v W的值告诉M F C新消息带一个指向C W n d类的指针,且返回值是Vo i d类型。然后,把正常情况下的w P a r a m和l P a r a m参数转换为调用参数。A f x S i g _ v W的其他可用值,请参阅M F C子目录下A F X M S G _ . H文件。改变A f x S i g _ v W的值意味着改变这个宏定义的函数的调用参数。2) 使用文本编辑器添加新消息处理函数的定义到接收消息类中。使用以下语法并保证是在C l a s s Wi z a r d的{{ }}框架之后,以防止C l a s s Wi z a r d删去所做的工作。
/ / { { A F X _ M S G ( C M a i n F r a m e )
/ / } } A F X _ M S G
afx_msg void OnMyMessage(CWnd *pWnd);<<<<
D E C L A R E _ M E S S A G E _ M A P ( )3) 在实现文件中,加入新消息映像宏到消息映像中。
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
/ / { { A F X _ M S G _ M A P ( C M a i n F r a m e )
/ / } } A F X _ M S G _ M A P
O N _ W Z D _ M E S S A G E ( W M _ W Z D _ M E S S A G E , O n M y M e s s a g e ) < < < < <
E N D _ M E S S A G E _ M A P ( )4) 最后,加入新消息处理函数。
void CMainFrame::OnWzdMessage(CWnd *pWnd)
{
/ / p r o c e s s
}
记住,这里传递的参数不是通常的w P a r a m和l P a r a m,而是更友好的C W n d指针。
说明
■ 窗口消息的主要目的是窗口之间的内部消息处理,而不是处理诸如来自菜单的命令消息。
添加一个新的命令消息,则要定义一个新的命令I D,而不是使用W M _ C O M M A N D。
■ 添加任何内容到映像中时,应避免把代码放在{{ }}框架之间。否则C l a s s Wi z a r d会把它
删去。
/ / { { A F X _ M S G _ M A P ( C M a i n F r a m e )
<---- NOT HERE!!!
/ / } } A F X _ M S G _ M A P
ON_WZD_MESSAGE() <---- HERE!!!!
■ 关于消息的详细内容参见第3章。例8有一个关于消息处理的实际例子。
CD说明
在C D上执行该工程时,单击O p t i o n s / W z d菜单命令,视图类发送一个客户窗口消息
( W M _ W Z D _ M E S S A G E )到主框架类。
可以加入:比如你的消息
#define WM_YOURMSG WM_USER+100
如果要加入CMainFrame的消息映射,则在MainFrame.h中加入处理函数:
afx_msg LRESULT OnUser(WPARAM wParam, LPARAM lParam);然后在cpp文件(MainFrame.cpp)中的消息映射中加入:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_MESSAGE(YOURMSG, OnUser)
END_MESSAGE_MAP()然后写OnUser的实现就行。
///////////////////////////////////////////////////////////////////
多年的珍藏都拿出来了。