zoukankan      html  css  js  c++  java
  • MFC 如何添加自定义消息

     

    MFC 如何添加自定义消息

    分类: MFC
    MFC如何添加自定义消息
     
     
     
     
     

    如果用户自定义的类要求响应普通的Windows消息(也就是以WM_开头,除了WM_COMMAND以外的消息,这类消息在WM_USER以下的是系统消息,WM_USER以上的可以由用户自己定义),那就要求自定义的类必须从CWnd中派生。这是由于此类消息的处理机制决定的,这类消息没有命令消息那条繁琐的流动路径,而是消息发出者直接发给对应

          CWnd的窗体句柄,由CWnd负责消息的响应。所以这类消息必须同一个CWnd类对应,更精确的说必须与一个HWND类型的窗体句柄相对应。这样得出一个重要的结论,就是从CCmdTarget中派生而没有从CWnd派生的类没有处理此类消息的能力。

         综上所述,就是为什么命令消息可以放到大部分类中处理,包括CWinThread、CWinApp、CDocument、CView、CFrameWnd或是自定义的类中,而普通Windows消息和用户自定义的消息只能放到CFrameWnd和CView等派生与CWnd中的类中处理。

          由此可见,我们自定义的类要想响应自定义消息就只能从CWnd中派生(当然不响应任何消息的类可以从CObject中派生)。先来看看如何自定义消息:

    在.h中做的工作:

    第一步要声明消息:

    #define WM_MYMSG WM_USER+8

    第二步要在类声明中声明消息映射:

    DECLARE_MESSAGE_MAP()

    第三步要在类声明中定义消息处理函数:

    afx_msg LRESULTMyMsgHandler(WPARAM,LPARAM);

    在.cpp中做的工作:

    第四步要实现消息映射:

    BEGIN_MESSAGE_MAP(CMainFrame,CMDIFrameWnd)

    ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)

    END_MESSAGE_MAP()

    第五步要实现消息处理函数(当然可以不实现):

    LRESULTCMainFrame::OnMyMsgHandler(WPARAM w,LPARAM l)

    {

    AfxMessageBox("Hello,World!");

    return 0;

    }

    在引发或发出消息的地方只用写上:

    ::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);

    到此,自定义消息完毕,这是好多网上文章都写的东西。大家会发现上面代码是在CMainFrame类中实现的,但是如果要用自定义类,就没有那么简单了。显然把第四步与第五步的CMainFrame换成自定义的类名(这里我用CMyTestObject来代表自定义类)是不能正常工作的。原因在于在发送消息的SendMessage函数中的第一个参数是

    要响应消息对应的HWND类型的窗体句柄,而CMyTestObject类中的m_hWnd中在没有调用CWnd::Create之前是没有任何意义的,也就是没有调用CWnd::Create或CWnd::CreateEx函数时,CWnd不对应任何窗体,消息处理不能正常运作。

    所以,又一个重要的结论,在自定义类能够处理任何消息之前一定要确保m_hWnd关联到一个窗体,即便这个窗体是不可见的。那么有人说,在自定义类的构造函数中调用Create函数就行了,不错,当然也可以在别处调用,只要确保在消息发送之前。但是,Create的调用很有说法,要注意两个地方,第一个参数是类的名称,我建议最好设为NULL;第五个参数是父窗体对象的指针,这个函数指定的对象一定要存在,我建议最好为整个程序的主窗体。还有很多人问第六个参数的意义,这个参数关系不大,是子窗体ID,用于传给父窗体记录以便识别。如下是我

    的自定义类的构造函数:

    CMyTestObject::CMyTestObject()

    {

    CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),::AfxGetMainWnd(),1234);

    }   //一定要在生成主窗体后使用,在主窗体完成OnCreate消息的处理后

    CMyTestObject::CMyTestObject(CWnd*pParent)

    {

    CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),pParent,1234);

    }

    不能如下调用Create,因为此时CMyTestObject不关联任何窗体,所以this中的m_hWnd无效:

    CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),this,1234);

    这时上面四、五两步修改成:

    BEGIN_MESSAGE_MAP(CMyTestObject,CWnd)

    ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)

    END_MESSAGE_MAP()

    LRESULTCMyTestObject::OnMyMsgHandler(WPARAM w,LPARAM l)

    {

    AfxMessageBox("My Messge Handler in MySelf-Custom Class!");

    return 0;

    }

    在类外部发出消息:

    CMyTestObject *test=newCMyTestObject();

    ::SendMessage(test->m_hWnd,WM_MYMSG,0,0);

    在类内部某个成员函数(方法)中发出消息:

    ::SendMessage(m_hWnd,WM_MYMSG,0,0);

    最后一个问题便是容易产生警告错误的窗体回收,自定义的类要显式调用窗体销毁,析构函数如下:

    CMyTestObject::~CMyTestObject()

    {

    CWnd::DestroyWindow();

    }

  • 相关阅读:
    JSP简单访问数据库
    解析数据存储MySQL
    学习SSH框架
    JavaWEB中读取配置信息
    Eclipse中将Java项目转换成Web项目的方法
    JavaWEB入门
    万能数据库连接类-Oracle、DB2 、Access 、Sql Server
    小米3 打开开发者选项
    coolpad 5879logcat不能输入日志解决办法
    实用开发之-oracle表回滚到一个指定时间的操作语句
  • 原文地址:https://www.cnblogs.com/jack-jia-moonew/p/4186646.html
Copyright © 2011-2022 走看看