消息映射、循环机制是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>