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"))
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Windows消息投递流程:WM_COMMAND消息流程

该示例通过研究基本的单文档程序的“文件”--“打开”命令,分析WM_COMMAND消息投递流程。基于VS 2005 代码 AfxWndProc最终调用的是OnWndMsg,这个函数负责消息的分发处理。...

MQ消息完整流程

public class QueueManger { private static string QueuePath = @".\private$\{0}"; ...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Windows消息机制流程

文章一:较为精简的windows消息机制的解释 【摘自】http://www.mianwww.com/html/2012/04/15213.html Windows消息机制的流程: ...

Cocoa消息处理流程

最近看了一些文章,觉得很不错,因为这方面的文章关于细节部分的讲解比较多,重点推荐罗朝晖的两篇文章(将在本文附件中给出文章链接),所以就不再重复刷,就大致讲解一下消息响应的处理流程;       一般...

android 消息传递流程

原文:http://blog.chinaunix.net/uid-2630593-id-2138607.html 记的以前写过系统如何在驱动中生成消息,包装消息,丢到消息队列。现在和大家...

Windows消息机制流程

文章一:较为精简的windows消息机制的解释 【摘自】http://www.mianwww.com/html/2012/04/15213.html Windows消息机制的流程: ...

Libevent中读消息流程

关于接收监听并建立连接得到通讯套接字过程请参考Libevent监听事件的建立过程文档。 涉及到的几个结构体   struct bufferevent_private {          ...

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

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

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

核心原理 Notify在设计思路上与传统的MQ有一定的不同,他的核心设计理念是 为了消息堆积而设计系统 无单点,可自由扩展的设计 下面就请随我一起,进入到我们的消息系统内部来看...

duilib 第二天 2016年6月三日

看了几个例子,照着做可以做出来,但是不看例子自己不会实现,还是没有理解最为本质的东西,今天开始学习duilib消息流程 看下CWindowWnd类与CPaintManagerUI类是...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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