金山界面库分析(6)

消息和事件的传递、分发、相应


既然没有真实的窗口,那么也就不能使用windows的根据句柄来分发消息的方式了,我们需要创建自己的消息和事件分发体系。主要应该包括这几个方面:

1.      接收真实窗口的消息,并将其转化虚窗口体系中的处理

2.      虚窗口体系内有一套独立的消息分发机制,可以讲系统消息发至该接收的控件

3.      虚窗口需要能够抛出事件的能力,因为虚窗口之间也需要有相互的通知和相应的能力,那么就需要虚窗口可以对于指定窗口抛出事件

4.      对于3中所抛出的事件,可以传递到指定的控件,并且控件内部应该有一套指定额相应体系

在CBkDialogViewImpl中使用WTL的消息分发方法用于系统消息的分发:

   BEGIN_MSG_MAP_EX(CBkDialogViewImpl)

       MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST,OnToolTipEvent)

       MSG_WM_SIZE(OnSize)

       MSG_WM_PRINT(OnPrint)

       MSG_WM_PAINT(OnPaint)

        //……从略

       NOTIFY_CODE_HANDLER_EX(BKINM_INVALIDATERECT, OnBKINMInvalidateRect)

       REFLECT_NOTIFY_CODE(NM_CUSTOMDRAW)

       MESSAGE_HANDLER_EX(WM_NOTIFY, OnChildNotify)

       MESSAGE_HANDLER_EX(WM_COMMAND, OnChildNotify)

       MESSAGE_HANDLER_EX(WM_VSCROLL, OnChildNotify)

       MESSAGE_HANDLER_EX(WM_HSCROLL, OnChildNotify)

       REFLECT_NOTIFICATIONS_EX()

END_MSG_MAP()

下面的是对于WM_SIZE消息的分发过程:

 

在CBkWindow类中创建了用于发送通知的函数:

 

  // Send a message to BkWindow
   LRESULT BkSendMessage(UINT Msg, WPARAM wParam =0, LPARAM lParam= 0)
   {
       LRESULT lResult= 0;
        if ( Msg < WM_USER
            &&Msg != WM_DESTROY
            &&Msg != WM_CLOSE
            )
        {
            TestMainThread();
        }
       SetMsgHandled(FALSE);
       ProcessWindowMessage(NULL, Msg, wParam, lParam,lResult);
       return lResult;
   }

这个函数很像windows的消息发送函数SendMessage,

LRESULT SendMessage(HWND hWnd, UINT Msg,WPARAM wParam, LPARAM IParam)

需要向那个对象发送消息,那么首先需要获取这个对象,然后调用这个对象的BkSendMessage函数,用消息类型和附属参数填充,就可以完成事件通知的过程了。

在这个函数中调用了ProcessWindowMessage方法,但是我们并没有看见这个函数的实现,我们来找一下哈~~


我们点击调用栈里面的ProcessWindowMessage方法,程序转到了CBkWindow类的这块:

   BKWIN_BEGIN_MSG_MAP()

       MSG_WM_CREATE(OnCreate)

       MSG_WM_PAINT(OnPaint)

       MSG_WM_DESTROY(OnDestroy)

       MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)

       MSG_WM_NCCALCSIZE(OnNcCalcSize)

       MSG_WM_SHOWWINDOW(OnShowWindow)

BKWIN_END_MSG_MAP_BASE()

难道就是这串宏实现了实现了通知的相应机制,我们来分析一下这个几个宏的实现。

// BkWindow Message MapDefine
// Use WTL Message Map Ex(include atlcrack.h)
#define BKWIN_BEGIN_MSG_MAP()                                       \
protected:                                                         \
    virtual BOOL ProcessWindowMessage(                              \
       HWND hWnd,UINT uMsg,WPARAM wParam,                        \
       LPARAM lParam,LRESULT& lResult)                            \
    {                                                              \
#define BKWIN_END_MSG_MAP()                                         \
       if (!IsMsgHandled())                                        \
            return__super::ProcessWindowMessage(                   \
                hWnd,uMsg, wParam,lParam, lResult);               \
       return TRUE;                                                \
    }                                                              \
#define BKWIN_END_MSG_MAP_BASE()                                    \
       return TRUE;                                               \
}                                                               \

上面的是自定义的,而其他则是使用的WTL的宏,如:

// intOnCreate(LPCREATESTRUCT lpCreateStruct)
#define MSG_WM_CREATE(func)\
    if (uMsg == WM_CREATE) \
    {\
        SetMsgHandled(TRUE);\
        lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \
        if(IsMsgHandled())\
            return TRUE; \
}

我们将宏展开看一下就是:

protected:                                                         
         virtualBOOL ProcessWindowMessage(                             
       HWND hWnd, UINT uMsg, WPARAM wParam,                       
       LPARAM lParam, LRESULT& lResult)                           
         {
         if(uMsg == WM_CREATE)
         {
                   SetMsgHandled(TRUE);
                   lResult= (LRESULT) OnCreate ((LPCREATESTRUCT)lParam);
                   if(IsMsgHandled())
                            returnTRUE;
         }
        //......此处略去其他分发函数                       
       return TRUE;                                              
         } 

可见就是给每个虚窗口类增加了一个函数ProcessWindowMessage,而这个函数的作用就是根据发送通知的不同来选择处理的函数,也就是BkSendMessageàProcessWindowMessageà根据消息的不同选择不同的处理函数,并且这个函数和消息我们可以自己进行搭配的,可能是为了简便使用了系统消息宏,其实我们也可以自己进行定义的。比如定义一个消息为BKM_CREATE,那么定义一个宏:

#define MSG_BKM_CREATE(func)\

    if (uMsg == BKM_CREATE) \

    {\

        SetMsgHandled(TRUE);\

        lResult = (LRESULT)func((LPCREATESTRUCT)lParam); \

        if(IsMsgHandled())\

            return TRUE; \

}

就可以自己来定义通知的类型了。

对于CBkWindow,因为它是所有虚窗口的基类,所以消息处理到此为止,ProcessWindowMessage函数最后什么都没做,使用了BKWIN_END_MSG_MAP_BASE宏。

在CBkWindow子类中,我们将BKWIN_END_MSG_MAP_BASE替换为BKWIN_END_MSG_MAP,那么宏展开了就是:

protected:                                                         
         virtualBOOL ProcessWindowMessage(                             
       HWND hWnd, UINT uMsg, WPARAM wParam,                       
       LPARAM lParam, LRESULT& lResult)                            
         {
         if(uMsg == WM_CREATE)
         {
                   SetMsgHandled(TRUE);
                   lResult= (LRESULT)func((LPCREATESTRUCT)lParam);
                   if(IsMsgHandled())
                            returnTRUE;
         }
       //......此处略去其他分发函数    
       if (!IsMsgHandled())                                  
            return__super::ProcessWindowMessage(                  
                hWnd, uMsg, wParam, lParam,lResult);              
       return TRUE;                                               
         }

__super::ProcessWindowMessage完整的链式消息传递啊~~,对于子类处理之后的消息还行传递给父类进行处理就可以这么搞了~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值