如何在MFC中自定义消息

消息映射、循环机制是Windows程序运行的基本方式。VC++   MFC   中有许多现成的消息句柄,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难。在MFC   ClassWizard中不允许添加用户自定义消息,所以我们必须在程序中添加相应代码,以便可以象处理其它消息一样处理自定义消息。通常的做法是采取以下步骤:  
   
    第一步:定义消息。  
   
    推荐用户自定义消息至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。  
   
  #define   WM_MY_MESSAGE   (WM_USER+100)      
   
    第二步:实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT。    
   
  LPESULT   CMainFrame::OnMyMessage(WPARAM   wParam,   LPARAM   lParam)    
  {    
  //   TODO:   处理用户自定义消息    
  ...    
  return   0;    
  }      
   
    第三步:在类头文件的AFX_MSG块中说明消息处理函数:  
   
  class   CMainFrame:public   CMDIFrameWnd    
  {    
  ...    
  //   一般消息映射函数    
  protected:    
  //   {{AFX_MSG(CMainFrame)    
  afx_msg   int   OnCreate(LPCREATESTRUCT   lpCreateStruct);    
  afx_msg   void   OnTimer(UINT   nIDEvent);    
  afx_msg   LRESULT   OnMyMessage(WPARAM   wParam,   LPARAM   lParam);    
  //}}AFX_MSG    
  DECLARE_MESSAGE_MAP()    
  }    
   
    第四步:在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消息处理函数中。    
   
  BEGIN_MESSAGE_MAP(CMainFrame,   CMDIFrameWnd)    
  //{{AFX_MSG_MAP(CMainFrame)    
  ON_WM_CREATE()    
  ON_WM_TIMER()    
  ON_MESSAGE(WM_MY_MESSAGE,   OnMyMessage)    
  //}}AFX_MSG_MAP    
  END_MESSAGE_MAP()    
  如果用户需要一个定义整个系统唯一的消息,可以调用SDK函数RegisterWindowMessage定义消息:  
   
  static   UINT   WM_MY_MESSAGE=RegisterWindowMessage("User");    
   
    并使用ON_REGISTERED_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步骤同上。  
   
    当需要使用自定义消息时,可以在相应类中的函数中调用函数PostMessage或SendMessage发送消息PoseMessage(WM_MY_MESSAGE,O,O);   如果向其他进程发送消息可通过如下方法发送消息:  
   
  DWORD   result;  
  SendMessageTimeout(wnd->m_hWnd,   //   目标窗口  
  WM_MY_MESSAGE,   //   消息  
  0,   //   WPARAM  
  0,   //   LPARAM  
  SMTO_ABORTIFHUNG   |  
  SMTO_NORMAL,  
  TIMEOUT_INTERVAL,  
  &result);    
  以避免其它进程如果被阻塞而造成系统死等状态。  
   
    可是如果需要向其它类(如主框架、子窗口、视类、对话框、状态条、工具条或其他控件等)发送消息时,上述方法显得无能为力,而在编程过程中往往需要获取其它类中的某个识别信号,MFC框架给我们造成了种种限制,但是可以通过获取某个类的指针而向这个类发送消息,而自定义消息的各种动作则在这个类中定义,这样就可以自由自在的向其它类发送消息了。  
   
    下面举的例子叙述了向视类和框架类发送消息的方法:  
   
    在主框架类中向视类发送消息:  
   
    视类中定义消息:  
   
  ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage)   //定义消息映射  
  视类定义消息处理函数:  
   
  //   消息处理函数  
  LRESULT   CMessageView::OnMyMessage(WPARAM   wParam,   LPARAM   lParam)  
  {  
  //   TODO:   处理用户自定义消息    
  ...    
  return   0;  
  }    
   
  //发送消息的测试函数  
  void   CMainFrame::OnTest()  
  {  
  CView   *   active   =   GetActiveView();//获取当前视类指针  
  if(active   !=   NULL)  
  active->PostMessage(WM_MY_MESSAGE,0,0);  
  }    
   
    在其它类中向视类发送消息:  
   
  //发送消息的测试函数  
  void   CMainFrame::OnTest()  
  {  
  CMDIFrameWnd   *pFrame;  
  CMDIChildWnd   *pChild;  
  CView   *pView;  
  //获取主窗口指针  
  pFrame   =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;  
  //   获取子窗口指针  
  pChild   =   (CMDIChildWnd   *)   pFrame->GetActiveFrame();  
  //获取视类指针  
  pView   =   pChild->GetActiveView();  
  if(pView   !=   NULL)  
  pView->PostMessage(WM_MY_MESSAGE,0,0);//发送消息  
  }    
   
    其余步骤同上。  

在视类中向主框架发送消息:  
   
    首先在主框架中定义相关的消息,方法同上,然后在发送消息的函数中添加代码如下  
   
  //发送消息的测试函数  
  void   CMessageView::OnTest()  
  {  
  CFrameWnd   *   active   =   GetActiveFrame();//获取当前主窗口框架指针  
  if(active   !=   this)  
  active->PostMessage(WM_MY_MESSAGE,0,0);  
  return   0;  
  }    
   
    在其它类中向不同的类发送消息可依次方法类推,这样我们的程序就可以的不受限制向其它类和进程发送消息,而避免了种种意想不到的风险。  
   
    下面一个例子程序为多文档程序里在一对话框中向视类发送消息,详述了发送自定义消息的具体过程。  
  实现步骤:  
   
    第一步:在VC++中新建工程Message,所有ClassWizard步骤选项均为缺省,完成。  
   
    第二步:在主菜单中添加测试菜单为调出对话框,在框架类中建立相应函数OnTest()  
   
    第三步:在资源中建立对话框,通过ClassWizard添加新类TestDialog,添加测试按钮,  
   
    在对话框类中建立相应函数OnDialogTest()  
   
  //通过对话框按钮发送消息的函数  
  void   TestDialog::OnDialogTest()  
  {  
  CMDIFrameWnd   *pFrame;  
  CMDIChildWnd   *pChild;  
  CView   *pView;  
  //获取主窗口指针  
  pFrame   =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;  
  //   获取子窗口指针  
  pChild   =   (CMDIChildWnd   *)   pFrame->GetActiveFrame();  
  //获取视类指针  
  pView   =   pChild->GetActiveView();  
  if(active   !=   NULL)  
  active->PostMessage(WM_MY_MESSAGE,0,0);//发送消息  
  }    
   
    在Message.h头文件中添加如下语句:  
   
  static   UINT   WM_MY_MESSAGE=RegisterWindowMessage("Message");    
   
    第四步:在视类中添加自定义消息:  
   
    在头文件MessageView.h中添加消息映射  
   
  protected:  
  //{{AFX_MSG(CMessageView)  
  //}}AFX_MSG  
  afx_msg   LRESULT   OnMyMessage(WPARAM   wParam,   LPARAM   lParam);   //此行为添加代码  
  DECLARE_MESSAGE_MAP()  
  在视类文件MessageView.cpp中的消息映射中添加自定义消息映射  
  BEGIN_MESSAGE_MAP(CMessageView,   CView)  
  //{{AFX_MSG_MAP(CMessageView)  
  //}}AFX_MSG_MAP  
  //   Standard   printing   commands  
  ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage)   //此行添加代码定义唯一消息  
  END_MESSAGE_MAP()    
   
    添加相应的0消息处理函数  
   
  LRESULT   CMessageView::OnMyMessage(WPARAM   wParam,   LPARAM   lParam)  
  {  
  CRect   rect;  
  GetClientRect(&rect);  
  InvalidateRect(&rect);  
  test=!test;  
  return   0;  
  }    
   
    在MessageView.h中添加布尔变量   public:BOOL   test;  
   
    在视类构造函数中初始化   test变量:test=FALSE;  
   
    修改CMessageView::OnDraw()函数  
   
  void   CMessageView::OnDraw(CDC*   pDC)  
  {  
  CMessageDoc*   pDoc   =   GetDocument();  
  ASSERT_VALID(pDoc);  
  //   以下程序显示消息响应效果  
  if(test)  
  pDC->TextOut(0,0,"消息响应!");  
  }    
   
    第五步:显示测试对话框  
   
    在MainFrame类中包含对话框头文件:  
   
  #include   "TestDialog.h";  
  OnTest()函数中添加代码  
  void   CMainFrame::OnTest()  
  {  
  TestDialog   dialog;  
  dialog.DoModal();  
  }    
   
    运行程序,在测试菜单打开对话框,点击测试按钮即可看到结果

猜你喜欢

转载自blog.csdn.net/hanllove001/article/details/5585238