4.Notify消息流程

原创 2016年08月31日 00:46:36

1.简介

如果想响应Notify事件,在自己的窗口的 HandleMessage() 函数中必须调用CPaintManagerUI::MessageHandler(),该函数处理了绝大部分常用的消息响应。

DuiLib将发送的Notify消息分为了同步和异步消息。同步就是立即调用,异步就是先放到队列中,下次再处理(类似PostMessage与SendMessage)。

2.发送Notify消息

CPaintManagerUI中有个函数用于程序主动发送Notify消息:

  • CPaintManagerUI::SendNotify(CControlUI*, LPCTSTR, WPARAM, LPARAM, bool)

该函数将PostMessage与SendMessage两个函数的功能集成在一个函数中,通过最后一个bool参数来区分同步消息或者异步消息:true:异步消息,false:同步消息。同步消息可以立马被执行,在消息被处理后,SendNotify() 才能返回;异步消息是先放在消息队列中,然后 SendNotify() 直接返回,异步消息会在窗口函数收到下一条消息的时候被处理。详细可以看代码:

void CPaintManagerUI::SendNotify(CControlUI* pControl, LPCTSTR pstrMessage, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/, bool bAsync /*= false*/)
{
    //对消息进行了封装
    TNotifyUI Msg;
    Msg.pSender = pControl;
    Msg.sType = pstrMessage;
    Msg.wParam = wParam;
    Msg.lParam = lParam;

    //发送消息还得看下面这个函数
    SendNotify(Msg, bAsync);
}

void CPaintManagerUI::SendNotify(TNotifyUI& Msg, bool bAsync /*= false*/)
{
    Msg.ptMouse = m_ptLastMousePos;
    Msg.dwTimestamp = ::GetTickCount();
    if( m_bUsedVirtualWnd )
    {
        Msg.sVirtualWnd = Msg.pSender->GetVirtualWnd();
    }

    if( !bAsync ) 
    {
        // Send to all listeners
        if( Msg.pSender != NULL ) 
        {
            //控件本身处理此消息
            if( Msg.pSender->OnNotify ) 
                Msg.pSender->OnNotify(&Msg);
        }
        for( int i = 0; i < m_aNotifiers.GetSize(); i++ ) 
        {
            //同步消息,被立即执行
            static_cast<INotifyUI*>(m_aNotifiers[i])->Notify(Msg);
        }
    }
    else 
    {
        //将消息存到堆上去
        TNotifyUI *pMsg = new TNotifyUI;
        pMsg->pSender = Msg.pSender;
        pMsg->sType = Msg.sType;
        pMsg->wParam = Msg.wParam;
        pMsg->lParam = Msg.lParam;
        pMsg->ptMouse = Msg.ptMouse;
        pMsg->dwTimestamp = Msg.dwTimestamp;

        //异步消息,被放在消息队列中
        m_aAsyncNotify.Add(pMsg);
    }
}

3.异步消息被处理

异步消息的处理时机:在窗口过程被执行的时候,即执行窗口的 HandleMessage() 的时候,且在 HandleMessage() 中调用了 CPaintManagerUI::MessageHandler()。原因在于异步消息只在CPaintManagerUI::MessageHandler()中进行处理。如下代码,将其他与异步消息无关代码已简化,并将异步消息处理提出成了一个函数:

bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
{
    //异步消息处理
    handleAsyncNotifyMsg();

    // 消息过滤

    // 普通消息处理
    switch( uMsg ) 
    {
        case WM_APP + 1:
        case WM_CLOSE:
        case WM_ERASEBKGND:
        case WM_PAINT: //重要,负责绘制窗口中的各个控件
        ....
    }

    // 异步消息处理:此处是为了处理上面switch时可能产生的一些异步消息
    handleAsyncNotifyMsg();

    return false;
}

//异步消息处理:循环取出异步消息,依次处理
void handleAsyncNotifyMsg()
{
    TNotifyUI* pMsg = NULL;
    while( pMsg = static_cast<TNotifyUI*>(m_aAsyncNotify.GetAt(0)) ) 
    {
        m_aAsyncNotify.Remove(0);
        if( pMsg->pSender != NULL ) 
        {
            if( pMsg->pSender->OnNotify ) pMsg->pSender->OnNotify(pMsg);
        }
        for( int j = 0; j < m_aNotifiers.GetSize(); j++ ) 
        {
            static_cast<INotifyUI*>(m_aNotifiers[j])->Notify(*pMsg);
        }
        delete pMsg;
    }
}

4.窗口的 Notify(TNotifyUI& msg) 函数

// Listener interface
class INotifyUI
{
public:
    virtual void Notify(TNotifyUI& msg) = 0;
};

bool CPaintManagerUI::AddNotifier(INotifyUI* pNotifier)
{
    ASSERT(m_aNotifiers.Find(pNotifier)<0);
    return m_aNotifiers.Add(pNotifier);
}

从上可知,Notify() 函数为 INotifyUI 定义的一个接口函数,所有的窗口都可以实现该函数。通过利用函数 AddNotifier() 注册监听,即可以处理Notify消息。

通过搜索发现, Notify() 函数在以下地方被调用:

  • void CPaintManagerUI::SendNotify(TNotifyUI& Msg, bool bAsync /= false/);
  • bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);

在上述第一个函数中,用于处理同步消息;在第二个函数中处理异步消息。而异步消息的入口也是 SendNotify() 函数,通过此函数将异步消息添加到队列中。依次可以得出结论:所有的notify消息都是通过 SendNotify() 函数来进入到notify消息处理中的。

5.结束

Duilib的所有消息类型如下:

#define DUI_MSGTYPE_MENU                   (_T("menu"))
#define DUI_MSGTYPE_LINK                   (_T("link"))

#define DUI_MSGTYPE_TIMER                  (_T("timer"))
#define DUI_MSGTYPE_CLICK                  (_T("click"))

#define DUI_MSGTYPE_RETURN                 (_T("return"))
#define DUI_MSGTYPE_SCROLL                 (_T("scroll"))

#define DUI_MSGTYPE_DROPDOWN               (_T("dropdown"))
#define DUI_MSGTYPE_SETFOCUS               (_T("setfocus"))

#define DUI_MSGTYPE_KILLFOCUS              (_T("killfocus"))
#define DUI_MSGTYPE_ITEMCLICK              (_T("itemclick"))
#define DUI_MSGTYPE_TABSELECT              (_T("tabselect"))

#define DUI_MSGTYPE_ITEMSELECT             (_T("itemselect"))
#define DUI_MSGTYPE_ITEMEXPAND             (_T("itemexpand"))
#define DUI_MSGTYPE_WINDOWINIT             (_T("windowinit"))
#define DUI_MSGTYPE_BUTTONDOWN             (_T("buttondown"))
#define DUI_MSGTYPE_MOUSEENTER             (_T("mouseenter"))
#define DUI_MSGTYPE_MOUSELEAVE             (_T("mouseleave"))

#define DUI_MSGTYPE_TEXTCHANGED            (_T("textchanged"))
#define DUI_MSGTYPE_HEADERCLICK            (_T("headerclick"))
#define DUI_MSGTYPE_ITEMDBCLICK            (_T("itemdbclick"))
#define DUI_MSGTYPE_SHOWACTIVEX            (_T("showactivex"))

#define DUI_MSGTYPE_ITEMCOLLAPSE           (_T("itemcollapse"))
#define DUI_MSGTYPE_ITEMACTIVATE           (_T("itemactivate"))
#define DUI_MSGTYPE_VALUECHANGED           (_T("valuechanged"))

#define DUI_MSGTYPE_SELECTCHANGED          (_T("selectchanged"))
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

WM_NOTIFY消息流程实例分析

  • 2012年10月10日 21:26
  • 856KB
  • 下载

阿里消息中间件notify源码

  • 2016年04月27日 13:52
  • 3.47MB
  • 下载

解读WM_NOTIFY消息中的NMHDR结构

NMHDR、LPNMTREEVIEW、TVITEM结构体   树控制的数据结构  在使用树控制时需要了解两个个非常重要的数据结构TV_ITEM和TV_INSERTSTRUCT,前一个数据结构是用来表示...
  • htt9931
  • htt9931
  • 2014年01月16日 12:57
  • 4157

淘宝notify-消息中间件(1)

淘宝的notify是一个非常有特色的消息中间件。它用创新地方式解决了分布式事务的问题,用相对较低的成本,实现了跨micro service的最终一致性。这种把最终一致性用application que...

WM_NOTIFY消息

当自定义控件中发生了特殊的事件需要通知父窗口时,可以向父窗口发送消息,最简单的方法就是直接向父窗口直接发送自定义消息:   this->GetParent()->SendMessage(...

关于WM_NOTIFY与消息反射————耗费我两天时间才解决的问题

谁让我这么菜呢!不过,没有菜鸟,哪来高手?-_-|其实,问题很简单,我想在listctrl响应NM_SETFOCUS的同时通知其父窗口(其实我这句话说错了,listctrl只能响应=NM_SETFOC...
  • zmq5411
  • zmq5411
  • 2011年02月15日 10:20
  • 1106

WM_COMMAND和WM_NOTIFY消息的区别

WM_COMMAND和WM_NOTIFY都是控件通知消息。        控件通知消息,是指这样一种消息,一个窗口内的控件发生了一些事情,需要通知父窗口。当用户与控件窗口交互时,控件通知消息就会...

ON_NOTIFY处理消息

这个技术文章介绍了关于新WM_NOTIFY消息, 还描述了建议使用的一种在你的MFC应用程序中处理WM_NOTIFY消息的方法。Windows 3.x 的 通告消息在Windows 3.x下,控件通过...

全面解读WM_NOTIFY & 消息反射

原文:http://blog.csdn.net/hustli/category/12732.aspx   摘要:控件通知消息有很多种,但是有一种是很常用,但是又不是很容易掌握的,那就是WM_N...
  • worldy
  • worldy
  • 2013年11月01日 17:09
  • 960

Posix消息队列 异步通知 mq_notify函数

System V消息队列的问题之一是无法通知一个进程何时在某个队列中放置了一个消息。采用轮询(poling),是对CPU时间的一种浪费。Posix消息队列容许 异步事件通知,以告知何时有一个消息放置到...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:4.Notify消息流程
举报原因:
原因补充:

(最多只允许输入30个字)