• =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

  • 相关阅读:
    CMLLVDS
    js获取url中的参数(解决中文乱码)
    解决跳转出现 No input file specified.
    ThinkPHP关联模型详解
    Thinkphp表单自动验证
    手机号登录注册
    JS实现每隔一段时间数量增加或减少
    文章或者观点说说等点赞功能实现(thinkphp)
    thinkphp整合Ueditor编辑器
    点击切换状态 类似开关按钮
  • 原文地址:https://www.cnblogs.com/findumars/p/6569319.html
Copyright © 2020-2023  润新知