消息映射、循环机制是Windows程序运行的基本方式。VC++ MFC 中有许多现成的消息句柄
,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难。在MFC
,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难。在MFC
<wbr><wbr><br>
ClassWizard中不允许添加用户自定义消息,所以我们必须在程序中添加相应代码,以便可<br>
以象处理其它消息一样处理自定义消息。通常的做法是采取以下步骤:<br><wbr><wbr><br>
第一步:定义消息。<br><wbr><wbr><br>
推荐用户自定义消息至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。<br><wbr><wbr><br>
#define WM_MY_MESSAGE (WM_USER+100) <wbr><wbr><br><wbr><wbr><br>
第二步:实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT。<wbr><wbr><br><wbr><wbr><br>
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)<wbr><wbr><br>
{ <wbr><wbr><br>
// TODO: 处理用户自定义消息 <wbr><wbr><br>
... <wbr><wbr><br>
return 0; <wbr><wbr><br>
} <wbr><wbr><br><wbr><wbr><br>
第三步:在类头文件的AFX_MSG块中说明消息处理函数:<br><wbr><wbr><br>
class CMainFrame:public CMDIFrameWnd<wbr><wbr><br>
{ <wbr><wbr><br>
... <wbr><wbr><br>
// 一般消息映射函数 <wbr><wbr><br>
protected: <wbr><wbr><br>
// {{AFX_MSG(CMainFrame) <wbr><wbr><br>
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);<wbr><wbr><br>
afx_msg void OnTimer(UINT nIDEvent);<wbr><wbr><br>
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);<wbr><wbr><br>
//}}AFX_MSG <wbr><wbr><br>
DECLARE_MESSAGE_MAP() <wbr><wbr><br>
} <wbr><wbr><br><wbr><wbr><br>
第四步:在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消息处理函数中。<br><wbr><wbr><br><wbr><wbr><br>
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)<wbr><wbr><br>
//{{AFX_MSG_MAP(CMainFrame) <wbr><wbr><br>
ON_WM_CREATE() <wbr><wbr><br>
ON_WM_TIMER() <wbr><wbr><br>
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)<wbr><wbr><br>
//}}AFX_MSG_MAP <wbr><wbr><br>
END_MESSAGE_MAP() <wbr><wbr><br><wbr><wbr><br>
如果用户需要一个定义整个系统唯一的消息,可以调用SDK函数RegisterWindowMessage定义<br>
消息:<br><wbr><wbr><br>
static UINT WM_MY_MESSAGE=RegisterWindowMessage("User");<wbr><wbr><br><wbr><wbr><br>
并使用ON_REGISTERED_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步骤同上。<br><wbr><wbr><br>
当需要使用自定义消息时,可以在相应类中的函数中调用函数PostMessage或SendMessa<br>
ge发送消息PoseMessage(WM_MY_MESSAGE,O,O); 如果向其他进程发送消息可通过如下方法<br>
发送消息:<br><wbr><wbr><br>
DWORD result;<br>
SendMessageTimeout(wnd->m_hWnd, // 目标窗口<br>
WM_MY_MESSAGE, // 消息<br>
0, // WPARAM<br>
0, // LPARAM<br>
SMTO_ABORTIFHUNG |<br>
SMTO_NORMAL,<br>
TIMEOUT_INTERVAL,<br>
&result); <wbr><wbr><br><wbr><wbr><br>
以避免其它进程如果被阻塞而造成系统死等状态。<br><wbr><wbr><br>
可是如果需要向其它类(如主框架、子窗口、视类、对话框、状态条、工具条或其他控<br>
件等)发送消息时,上述方法显得无能为力,而在编程过程中往往需要获取其它类中的某个<br>
识别信号,MFC框架给我们造成了种种限制,但是可以通过获取某个类的指针而向这个类发送<br>
消息,而自定义消息的各种动作则在这个类中定义,这样就可以自由自在的向其它类发送<br>
消息了。<br><wbr><wbr><br>
下面举的例子叙述了向视类和框架类发送消息的方法:<br><wbr><wbr><br>
在主框架类中向视类发送消息:<br><wbr><wbr><br>
视类中定义消息:<br><wbr><wbr><br>
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //定义消息映射<br>
视类定义消息处理函数:<br><wbr><wbr><br>
// 消息处理函数<br>
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAMlParam)<br>
{<br>
// TODO: 处理用户自定义消息 <wbr><wbr><br>
... <wbr><wbr><br>
return 0;<br>
} <wbr><wbr><br><wbr><wbr><br>
//发送消息的测试函数<br>
void CMainFrame::OnTest()<br>
{<br>
CView * active = GetActiveView();//获取当前视类指针<br>
if(active != NULL)<br>
active->PostMessage(WM_MY_MESSAGE,0,0);<br>
} <wbr><wbr><br><wbr><wbr><br>
在其它类中向视类发送消息:<br><wbr><wbr><br>
//发送消息的测试函数<br>
void CMainFrame::OnTest()<br>
{<br>
CMDIFrameWnd *pFrame;<br>
CMDIChildWnd *pChild;<br>
CView *pView;<br>
//获取主窗口指针<br>
pFrame=(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;<br>
// 获取子窗口指针<br>
pChild = (CMDIChildWnd *)pFrame->GetActiveFrame();<br>
//获取视类指针<br>
pView = pChild->GetActiveView();<br>
if(pView != NULL)<br>
pView->PostMessage(WM_MY_MESSAGE,0,0);//发送消息<br>
} <wbr><wbr><br><wbr><wbr><br>
其余步骤同上。<br><wbr><wbr><br>
在视类中向主框架发送消息:<br><wbr><wbr><br>
首先在主框架中定义相关的消息,方法同上,然后在发送消息的函数中添加代码如下<br><wbr><wbr><br>
//发送消息的测试函数<br>
void CMessageView::OnTest()<br>
{<br>
CFrameWnd * active = GetActiveFrame();//获取当前主窗口框架指针<br>
if(active != this)<br>
active->PostMessage(WM_MY_MESSAGE,0,0);<br>
return 0;<br>
} <wbr><wbr><br><wbr><wbr><br>
在其它类中向不同的类发送消息可依次方法类推,这样我们的程序就可以的不受限制<br>
向其它类和进程发送消息,而避免了种种意想不到的风险。<br><wbr><wbr><br>
下面一个例子程序为多文档程序里在一对话框中向视类发送消息,详述了发送自定义消<br>
息的具体过程。<br>
实现步骤:<br><wbr><wbr><br>
第一步:在VC++中新建工程Message,所有ClassWizard步骤选项均为缺省,完成。<br><wbr><wbr><br>
第二步:在主菜单中添加测试菜单为调出对话框,在框架类中建立相应函数OnTest()<br><wbr><wbr><br>
第三步:在资源中建立对话框,通过ClassWizard添加新类TestDialog,添加测试按钮,<br><wbr><wbr><br><wbr><wbr><br>
在对话框类中建立相应函数OnDialogTest()<br><wbr><wbr><br>
//通过对话框按钮发送消息的函数<br>
void TestDialog::OnDialogTest()<br>
{<br>
CMDIFrameWnd *pFrame;<br>
CMDIChildWnd *pChild;<br>
CView *pView;<br>
//获取主窗口指针<br>
pFrame=(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;<br>
// 获取子窗口指针<br>
pChild = (CMDIChildWnd *)pFrame->GetActiveFrame();<br>
//获取视类指针<br>
pView = pChild->GetActiveView();<br>
if(active != NULL)<br>
active->PostMessage(WM_MY_MESSAGE,0,0);//发送消息<br>
} <wbr><wbr><br><wbr><wbr><br>
在Message.h头文件中添加如下语句:<br><wbr><wbr><br>
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");<wbr><wbr><br><wbr><wbr><br>
第四步:在视类中添加自定义消息:<br><wbr><wbr><br>
在头文件MessageView.h中添加消息映射<br><wbr><wbr><br>
protected:<br>
//{{AFX_MSG(CMessageView)<br>
//}}AFX_MSG<br>
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);//此行为添加代码<br>
DECLARE_MESSAGE_MAP()<br>
在视类文件MessageView.cpp中的消息映射中添加自定义消息映射<br>
BEGIN_MESSAGE_MAP(CMessageView, CView)<br>
//{{AFX_MSG_MAP(CMessageView)<br>
//}}AFX_MSG_MAP<br>
// Standard printing commands<br>
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage)//此行添加代码定义唯一消息<br>
END_MESSAGE_MAP() <wbr><wbr><br><wbr><wbr><br>
添加相应的0消息处理函数<br><wbr><wbr><br>
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAMlParam)<br>
{<br>
CRect rect;<br>
GetClientRect(&rect);<br>
InvalidateRect(&rect);<br>
test=!test;<br>
return 0;<br>
} <wbr><wbr><br><wbr><wbr><br>
在MessageView.h中添加布尔变量 public:BOOL test;<br><wbr><wbr><br>
在视类构造函数中初始化 test变量:test=FALSE;<br><wbr><wbr><br>
修改CMessageView::OnDraw()函数<br><wbr><wbr><br>
void CMessageView::OnDraw(CDC* pDC)<br>
{<br>
CMessageDoc* pDoc = GetDocument();<br>
ASSERT_VALID(pDoc);<br>
// 以下程序显示消息响应效果<br>
if(test)<br>
pDC->TextOut(0,0,"消息响应!");<br>
} <wbr><wbr><br><wbr><wbr><br>
第五步:显示测试对话框<br><wbr><wbr><br>
在MainFrame类中包含对话框头文件:<br><wbr><wbr><br>
#include "TestDialog.h";<br>
OnTest()函数中添加代码<br>
void CMainFrame::OnTest()<br>
{<br>
TestDialog dialog;<br>
dialog.DoModal();<br>
} <wbr><wbr><br><wbr><wbr><br>
运行程序,在测试菜单打开对话框,点击测试按钮即可看到结果。</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>