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

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

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

消息映射宏声明:

  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()

消息响应函数

  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. CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);
  6. }
  7. //响应“=WM_VSCROLL”消息
  8. void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
  9. {
  10. // TODO: Add your message handler code here
  11. }

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

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

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

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

CMyScrollBar   m_Vsrcrollbar;

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

  1. //初始化垂直滚动条
  2. int i_scroMax = 100;
  3. m_Vscrollbar.SetScrollRange(0,i_scroMax);
  4. m_Vscrollbar.SetScrollPos(50);

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

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

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

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

  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. case SB_LINEDOWN:
  14. if( pos < Maxpos )
  15. pos += INT_SBLINEDOWN;
  16. break;
  17. case SB_PAGEUP:
  18. if( pos-INT_SBPAGEUP > Minpos )
  19. pos -= INT_SBPAGEUP;
  20. else
  21. pos = Minpos;
  22. break;
  23. case SB_PAGEDOWN:
  24. if( pos+INT_SBPAGEDOWN < Maxpos )
  25. pos += INT_SBPAGEDOWN;
  26. else
  27. pos = Maxpos;
  28. break;
  29. case SB_THUMBPOSITION:
  30. pos = nPos;
  31. break;
  32. }
  33. SetScrollPos(pos,TRUE);
  34. }

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

  1. CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)

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

  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函数中初始化上面的变量

  1. int i_scroMax = 100;
  2. m_scrolbar.SetScrollRange(0,i_scroMax);
  3. m_scrolbar.SetScrollPos(50);

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

  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. case SB_LINEDOWN:
  14. if( pos < Maxpos )
  15. pos += INT_SBLINEDOWN;
  16. break;
  17. case SB_PAGEUP:
  18. if( pos-INT_SBPAGEUP > Minpos )
  19. pos -= INT_SBPAGEUP;
  20. else
  21. pos = Minpos;
  22. break;
  23. case SB_PAGEDOWN:
  24. if( pos+INT_SBPAGEDOWN < Maxpos )
  25. pos += INT_SBPAGEDOWN;
  26. else
  27. pos = Maxpos;
  28. break;
  29. case SB_THUMBPOSITION:
  30. pos = nPos;
  31. break;
  32. }
  33. m_scrolbar.SetScrollPos(pos,TRUE);
  34. CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
  35. }

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

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

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

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

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

3、总结

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

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

=WM_VSCROLL(消息反射) 和 WM_VSCROLL(消息响应)的区别(控件拥有者自己不处这个理消息,而是反射给控件对象本身来处理这个消息)的更多相关文章

  1. 【C#】无损转换Image为Icon 【C#】组件发布:MessageTip,轻快型消息提示窗 【C#】给无窗口的进程发送消息 【手记】WebBrowser响应页面中的blank开新窗口及window.close关闭本窗体 【手记】调用Process.EnterDebugMode引发异常:并非所有引用的特权或组都分配给呼叫方 【C#】DataRowState演变备忘

    [C#]无损转换Image为Icon 如题,市面上常见的方法是: var handle = bmp.GetHicon(); //得到图标句柄 return Icon.FromHandle(handle ...

  2. LockWindowUpdate的函数的用法(不忽略消息,只是暂时不响应,但WM_SETREDRAW根本不接受重绘消息)

    Application.ProcessMessages;LockWindowUpdate(Self.Handle);  //锁住当前窗口 LockWindowUpdate(0)//解除锁定窗口 Loc ...

  3. Objective-c中的对象间的消息传递以及消息路由

    刚开始使用Objective-C时,总是习惯将对象间发送消息之间称呼为方法调用.心想,这和c#不是一回事吗?不就是调用实例方法吗,还搞个消息发送作甚,最后还不是要转化为方法的调用?通过一段时间的理解学 ...

  4. Delphi 消息函数 SendMessage函数和 PostMessage的区别

    SendMessage函数 将指定的消息发到窗口.它调用特定窗口的窗口处理函数,并且不会立即返回,直到窗口处理函数处理了这个消息. PostMessage函数 将一个消息放入与创建这个窗口的消息队列相 ...

  5. 反射,内省,BeanUtil的区别

    PS:为了操作反射方便,sun创建了 内省, Apache闲麻烦自己创建了BeanUtils 1.开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所 ...

  6. Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法

    Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...

  7. python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法

    目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ...

  8. WCF消息交换模式之请求-响应模式

    WCF的消息交换模式(MEP)有三种:请求/响应.单向模式和双工模式.WCF的默认MEP是请求/响应模式. 请求/响应模式操作签名代码如下,无需指定模式,默认就是. [OperationContrac ...

  9. 消息点击事件的响应链---hitTest:withEvent:方法

    *当用户点击屏幕时,会产生一个触摸事件,系统会将触摸事件加入到 UIApplication管理事件队里中 *UIApplication 会从事件队列中取出最前面的事件进行分发以便处理,通常,先发送事件 ...

随机推荐

  1. RGB 的调色

    通过 RGB 三通道所占比的组合(通过三元素长的元组存储),可呈现丰富的色彩样式: [0, 0, 0] ⇒ 黑色,[1, 1, 1] ⇒ 白色 [1, 0, 0] ⇒ 红色,[0, 1, 0] ⇒ 绿 ...

  2. 【序列操作I】线段树

    题目描述 Lxhgww 最近收到了一个 01 序列,序列里面包含了 n(1≤n≤105)个数,这些书要么是 0,要么是 1,现在对这个序列有五种变换操作和询问操作:1. 0 a b ,把[a,b]区间 ...

  3. TCP基础

    TCP基础知识 复习   前言 说来惭愧,大二时候学的计算机网络好多都不太记得了,不过还好有认真学过,捡起来也挺快的,就是对于现在业界中使用的网络算法的不是很懂: 1 TCP报文段结构 1.1 序号和 ...

  4. Android菜鸟的成长笔记(21)——跨进程调用Service

    我们都知道在Android中的每一个应用是一个进程,其实每一个应用就相当于Linux系统里面的一个用户,进程和进程之间的通信其实就相当于用户和用户之间的通信,为了实现这种跨进程通信,Android提供 ...

  5. WPF 使用不安全代码快速从数组转 WriteableBitmap

    原文:WPF 使用不安全代码快速从数组转 WriteableBitmap 本文告诉大家一个快速的方法,直接把数组转 WriteableBitmap 先来说下以前的方法,以前使用的是 BitmapSou ...

  6. JAVA自带API的压缩与解压

    Java API中的 java.util.zip.*;包下包含了Java对于压缩文件的所有相关操作.我们可以使用该包中的方法,结合IO中的相关知识,进行文件的压缩和解压缩相关操作. ZipFile j ...

  7. 采用API将AR应收账款未知未核销状态变成黄金

    DECLARE p_api_version NUMBER; p_init_msg_list VARCHAR2(200); p_commit VARCHAR2(200); p_validation_le ...

  8. 《Head First 设计模式》学习笔记——命令模式

    在软件系统,"行为请求者"与"行为实施者"通常存在一个"紧耦合".但在某些场合,比方要对行为进行"记录.撤销/重做.事务" ...

  9. Asp.net C# 获取本周上周本月上月本年上年第一天最后一天时间大全

    DateTime dt = DateTime.Now; int weeknow = Convert.ToInt32(DateTime.Now.DayOfWeek); ) * weeknow + ; D ...

  10. jQuery迭代器

    http://www.imooc.com/code/3417 迭代器 迭代器是一个框架的重要设计.我们经常需要提供一种方法顺序用来处理聚合对象中各个元素,而又不暴露该对象的内部,这也是设计模式中的迭代 ...