MFC添加自定义消息

来源:互联网 发布:淘宝打印发货单软件 编辑:程序博客网 时间:2024/06/05 05:46

    Windows应用程序所要做的每项工作几乎都是基于消息处理的, Windows 系统消息分为常用 Windows 消息,控件通知消息和命令。然而,有时我们需要定义自己的消息来通知程序什么事情发生了,这就是用户自定义消息。 ClassWizard 并没有提供增加用户自定义消息的功能,所以要使用用户自定义消息,必须手工编写代码。然后 ClassWizard 才可以象处理其它消息一样处理你自定义的消息。具体做法如下详解:

    第一步:定义消息。一个消息实际上是开发 Windows95 应用程序时, Microsoft 推荐用户自定义消息至少是 WM_USER+100,因为很多新控件也要使用 WM_USER 消息。

    第二步:实现消息处理函数。该函数使用 WPRAM 和 LPARAM 参数并返回 LPESULT 。

   LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)

     {

          // TODO: 处理用户自定义消息

          AfxMessageBox(" 处理用户自定义消息 ");

          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_MAPEND_MESSAGE_MAP()


    这样,一个用户自定义消息就可以使用了,如果用户需要一个整个系统唯一的消息,可以调用 SDK 函数 RegisterWindowMessage 并使用 ON_REGISTER_MESSAGE 宏指令取代 ON_MESSAGE 宏指令,其余步骤同上。

    VC++ 为程序员提供了一套功能强大、方便快捷的编程工具,它可以帮你方便的生成窗口、菜单等用户界面,可惜就是做出来的东西都一样,没有一点个性。下面,就介绍一些方法,让我们可以按照自己的设计定制出更加符合自己程序风格的窗口。
  如果用户需要一个定义整个系统唯一的消息,可以调用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框架给我们造成了种种限制,但是可以通过获取某个类的指针而向这个类发送消息,而自定义消息的各种动作则在这个类中定义,这样就可以自由自在的向其它类发送消息了。

 

  下面举的例子叙述了向视类和框架类发送消息的方法:

 

    1、在主框架类中向视类发送消息:

  视类中定义消息、消息处理函数:
    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);//发送消息
    }

 

    2、在视类中向主框架发送消息:

  首先在主框架中定义相关的消息,方法同上,然后在发送消息的函数中添加代码如下

  void CXXXView::OnTest() //多文档:发送消息的测试函数
    {
        CMDIFrameWnd *pFrame;
        CMDIChildWnd *pChild;
        //获取主窗口指针
        pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
        // 获取子窗口指针
        pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
        if(pChild != NULL)
            pChild ->PostMessage(WM_MY_MESSAGE,0,0);//发送消息
    }

 

  3、在其它类中向不同的类发送消息可依次方法类推,这样我们的程序就可以的不受限制向其它类和进程发送消息,而避免了种种意想不到的风险。

 

  下面一个例子程序为多文档程序里在一对话框中向视类发送消息,详述了发送自定义消息的具体过程。

    实现步骤:

    第一步:在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(pView != NULL)
            pView->PostMessage(WM_MY_MESSAGE,0,0);//发送消息
    }

  在Message.h头文件中添加如下语句:static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");

  第四步:在视类中添加自定义消息:

在头文件MessageView.h中:

    1、添加变量:public: BOOL test;

    2、添加消息映射:

    protected:
    //{{AFX_MSG(CMessageView)
    //}}AFX_MSG
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //此行为添加代码
    DECLARE_MESSAGE_MAP()
在视类文件MessageView.cpp中:

    1、在构造函数中初始化前面添加的变量:test = FALSE;

    2、在消息映射中添加自定义消息映射:
    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()

  3、添加相应的消息处理函数:

    LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
    {
        CRect rect;
        GetClientRect(&rect);
        InvalidateRect(&rect);
        test=!test;
        return 0;
    }

  4、修改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();
  }

  运行程序,在测试菜单打开对话框,点击测试按钮即可看到结果。

0 0
原创粉丝点击