zoukankan      html  css  js  c++  java
  • =WM_VSCROLL(消息反射) 和 WM_VSCROLL(消息响应)的区别(控件拥有者自己不处这个理消息,而是反射给控件对象本身来处理这个消息)

    =WM_VSCROLL(消息反射) 和 WM_VSCROLL(消息响应)的区别

    所谓消息反射就是控件拥有者自己不处这个理消息,而是反射给控件对象本身来处理这个消息

    1、“=WM_VSCROLL”是消息反射标志  , WM_VSCROLL是 消息响应的标志,在VC6.0的ClassWizard中注意会发现这两个不同的消息,VS2010中没有“=WM_VSCROLL”,但是可以通过手动添加:

    消息映射宏声明:    

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. BEGIN_MESSAGE_MAP(CMyScrollBar, CScrollBar)  
    2.     //{{AFX_MSG_MAP(CMyScrollBar)  
    3.     ON_WM_VSCROLL()           //普通消息  
    4.     ON_WM_VSCROLL_REFLECT()  //反射消息,由控件自身处理  
    5.     //}}AFX_MSG_MAP  
    6. END_MESSAGE_MAP()  

    消息响应函数

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //响应“WM_VSCROLL”消息  
    2. void CMyScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)   
    3. {  
    4.    // TODO: Add your message handler code here and/or call default    
    5.   
    6.    CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);  
    7. }  
    8.   
    9. //响应“=WM_VSCROLL”消息  
    10. void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)   
    11. {  
    12.     // TODO: Add your message handler code here  
    13. }  

              注意:上面两个“TODO”的内容是有区别的

    2、以MFC基于对话框工程来讲解:

           a.  CMyDialog,CMyApp,然后添加一个CMyScrollBar:public CScrollBar类

           b.   在MyDialog.h中添加垂直滚动条,绑定一个变量

                    CMyScrollBar   m_Vsrcrollbar;

          c.   在CMyDialog中OnInitDialog函数中初始化上面的变量

                

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //初始化垂直滚动条  
    2. int i_scroMax = 100;  
    3. m_Vscrollbar.SetScrollRange(0,i_scroMax);  
    4. m_Vscrollbar.SetScrollPos(50);  


           d.   为CMyScrollBar类添加"WM_VSCROLL"消息(这个消息是反射消息)响应函数 (通过ClassWiard)

                 

          

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #define INT_SBLINEUP 4  
    2. #define INT_SBLINEDOWN 4  
    3. #define INT_SBPAGEUP 25  
    4. #define INT_SBPAGEDOWN 25      //下面所有代码都会使用  
    5.   
    6. void CMyScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)   
    7. {  
    8.     // TODO: Add your message handler code here and/or call default  
    9.     int pos,*Minpos,*Maxpos;  
    10.     pos = GetScrollPos();  
    11.     GetScrollRange(Minpos,Maxpos);  
    12.     switch( nSBCode )  
    13.     {  
    14.     case SB_LINEUP:  
    15.         if( pos > *Minpos )  
    16.             pos -= INT_SBLINEUP;  
    17.         break;  
    18.   
    19.     case SB_LINEDOWN:  
    20.         if( pos < *Maxpos )  
    21.             pos += INT_SBLINEDOWN;  
    22.         break;  
    23.   
    24.     case SB_PAGEUP:  
    25.         if( pos-INT_SBPAGEUP > *Minpos )  
    26.             pos -= INT_SBPAGEUP;  
    27.         else  
    28.             pos = *Minpos;  
    29.         break;  
    30.   
    31.     case SB_PAGEDOWN:  
    32.         if( pos+INT_SBPAGEDOWN < *Maxpos )  
    33.             pos += INT_SBPAGEDOWN;  
    34.         else  
    35.             pos = *Maxpos;  
    36.         break;  
    37.   
    38.     case SB_THUMBPOSITION:  
    39.         pos = nPos;  
    40.         break;  
    41.   
    42.     }  
    43.     SetScrollPos(pos,TRUE);  
    44.     CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);  
    45. }  


              编译运行后,单击滚动条发现没有任何反应;在上面的函数上加断点,调试发现触发WM_VSCROLL消息后,根本没有调用这个函数。那么如何让CMyScrollBar类控件对象自己处理“WM_VSCROLL”消息呢?请看“第e步”。

          e.为CMyScrollBar类添加"=WM_VSCROLL"消息(这个消息是反射消息)响应函数 (通过类视图,右键单击类名|Add Windows Message Handler....,用ClassWizard也行)

                 

               

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)   
    2. {  
    3.     // TODO: Add your message handler code here  
    4.     int pos,Minpos=0,Maxpos=100;  
    5.     pos = GetScrollPos();  
    6.     GetScrollRange(&Minpos,&Maxpos);  
    7.     switch( nSBCode )  
    8.     {  
    9.     case SB_LINEUP:  
    10.         if( pos > Minpos )  
    11.             pos -= INT_SBLINEUP;  
    12.         break;  
    13.           
    14.     case SB_LINEDOWN:  
    15.         if( pos < Maxpos )  
    16.             pos += INT_SBLINEDOWN;  
    17.         break;  
    18.           
    19.     case SB_PAGEUP:  
    20.         if( pos-INT_SBPAGEUP > Minpos )  
    21.             pos -= INT_SBPAGEUP;  
    22.         else  
    23.             pos = Minpos;  
    24.         break;  
    25.           
    26.     case SB_PAGEDOWN:  
    27.         if( pos+INT_SBPAGEDOWN < Maxpos )  
    28.             pos += INT_SBPAGEDOWN;  
    29.         else  
    30.             pos = Maxpos;  
    31.         break;  
    32.           
    33.     case SB_THUMBPOSITION:  
    34.         pos = nPos;  
    35.         break;  
    36.           
    37.     }  
    38.     SetScrollPos(pos,TRUE);  
    39. }  

               运行后发现垂直滚动条可以很好的运行;调试发现,触发WM_VSCROLL消息后,会跳到下面这个函数中

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)  


             总结:两个消息的宏声明不一样            

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. BEGIN_MESSAGE_MAP(CMyScrollBar, CScrollBar)  
    2.     //{{AFX_MSG_MAP(CMyScrollBar)  
    3.     ON_WM_VSCROLL()      //普通消息  
    4.     ON_WM_VSCROLL_REFLECT()  //反射消息,由控件自身处理  
    5.     //}}AFX_MSG_MAP  
    6. END_MESSAGE_MAP()  


          f.  在MyDialog.h中添加垂直滚动条,绑定一个变量

                    CMyScrollBar   m_srcrolbar;

          g.   在CMyDialog中OnInitDialog函数中初始化上面的变量           

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. int i_scroMax = 100;  
    2. m_scrolbar.SetScrollRange(0,i_scroMax);  
    3. m_scrolbar.SetScrollPos(50);  


          h. 在CMyDialog类中响应WM_VSROLL消息响应

              

             

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. void CMyDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)  
    2. {  
    3.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
    4.     int pos,Minpos=0,Maxpos=0;  
    5.     pos = m_scrolbar.GetScrollPos();  
    6.     m_scrolbar.GetScrollRange(&Minpos,&Maxpos);  
    7.     switch( nSBCode )  
    8.     {  
    9.     case SB_LINEUP:  
    10.         if( pos > Minpos )  
    11.             pos -= INT_SBLINEUP;  
    12.         break;  
    13.   
    14.     case SB_LINEDOWN:  
    15.         if( pos < Maxpos )  
    16.             pos += INT_SBLINEDOWN;  
    17.         break;  
    18.   
    19.     case SB_PAGEUP:  
    20.         if( pos-INT_SBPAGEUP > Minpos )  
    21.             pos -= INT_SBPAGEUP;  
    22.         else  
    23.             pos = Minpos;  
    24.         break;  
    25.   
    26.     case SB_PAGEDOWN:  
    27.         if( pos+INT_SBPAGEDOWN < Maxpos )  
    28.             pos += INT_SBPAGEDOWN;  
    29.         else  
    30.             pos = Maxpos;  
    31.         break;  
    32.   
    33.     case SB_THUMBPOSITION:  
    34.         pos = nPos;  
    35.         break;  
    36.   
    37.     }  
    38.     m_scrolbar.SetScrollPos(pos,TRUE);  
    39.     CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);  
    40. }  

               运行发现m_srcolbar对象对应的控件可以正常的运行。因为这个OnVscroll函数中的代码是针对m_srcolbar对象设计的,故其可以正确运行。

         J.  上面的代码看起来很不和谐,有个办法能很好的解决这个问题,就是让绑定控件的变量m_Vscrollbar的类Child自己现实“WM_SCROLL”消息响应函数Child::OnVScroll函数,其父窗体类CFatherDlg也实现“WM_SCROLL”消息响应函数CFatherDlg::OnVScroll,然后用如下方式调用:

            Mark:20131215,(VC6/VS2010环境下调试)此函数被调用了两次,难以理解!即使为空函数体也是这种情况,求解!  

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //Mark:20131215  
    2. void CFatherDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)  
    3. {  
    4.   
    5.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
    6.     if( pScrollBar->GetDlgCtrlID() == m_Vscrollbar.GetDlgCtrlID()) //如果消息对应的控件ID号是我要处理的控件则进行对应处理  
    7.         {  
    8.            m_Vscrollbar.OnVScroll(nSBCode,nPos,pScrollBar);      
    9.         }   
    10.        //这样就可以针对控件的ID号分别控制多个垂直滚动条,而达到互不干扰、代码思路清晰的好处  
    11.   
    12. CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);  
    13. }  


             注意:上面的m_Vscrollbar对象的OnVscroll函数一定要声明成public访问权限,用ClassWizard添加的是Protected访问权限,可以自己手动改过来。

          

    3、总结

          如果要控件对应的对象自己处理一个消息,那么控件类自己必须实现“=WM_XXXX”反射响应函数;如果让控件的拥有者相对应的对象处理这个消息,那么应该在改对象的类中实现“WM_XXX”普通响应函数,并针对这个控件绑定的对象设计代码。

    http://blog.csdn.net/qq2399431200/article/details/17336455

  • 相关阅读:
    Android开发总结
    LeakCanary原理分析
    机器学习
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 3. 循环
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 2. 变量
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 1. 神秘朋友
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
    远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
  • 原文地址:https://www.cnblogs.com/findumars/p/6569319.html
Copyright © 2011-2022 走看看