=WM_VSCROLL(消息反射) 和 WM_VSCROLL(消息响应)的区别(控件拥有者自己不处这个理消息,而是反射给控件对象本身来处理这个消息)
2017-03-18 00:45
591 查看
=WM_VSCROLL(消息反射) 和 WM_VSCROLL(消息响应)的区别
所谓消息反射就是控件拥有者自己不处这个理消息,而是反射给控件对象本身来处理这个消息
1、“=WM_VSCROLL”是消息反射标志 , WM_VSCROLL是 消息响应的标志,在VC6.0的ClassWizard中注意会发现这两个不同的消息,VS2010中没有“=WM_VSCROLL”,但是可以通过手动添加:
消息映射宏声明:
[cpp] view plain copy
BEGIN_MESSAGE_MAP(CMyScrollBar, CScrollBar)
//{{AFX_MSG_MAP(CMyScrollBar)
ON_WM_VSCROLL() //普通消息
ON_WM_VSCROLL_REFLECT() //反射消息,由控件自身处理
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
消息响应函数
[cpp] view plain copy
//响应“WM_VSCROLL”消息
void CMyScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);
}
//响应“=WM_VSCROLL”消息
void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
{
// TODO: Add your message handler code here
}
注意:上面两个“TODO”的内容是有区别的
2、以MFC基于对话框工程来讲解:
a. CMyDialog,CMyApp,然后添加一个CMyScrollBar:public CScrollBar类
b. 在MyDialog.h中添加垂直滚动条,绑定一个变量
CMyScrollBar m_Vsrcrollbar;
c. 在CMyDialog中OnInitDialog函数中初始化上面的变量
[cpp] view plain copy
//初始化垂直滚动条
int i_scroMax = 100;
m_Vscrollbar.SetScrollRange(0,i_scroMax);
m_Vscrollbar.SetScrollPos(50);
d. 为CMyScrollBar类添加"WM_VSCROLL"消息(这个消息是反射消息)响应函数 (通过ClassWiard)
[cpp] view plain copy
#define INT_SBLINEUP 4
#define INT_SBLINEDOWN 4
#define INT_SBPAGEUP 25
#define INT_SBPAGEDOWN 25 //下面所有代码都会使用
void CMyScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
int pos,*Minpos,*Maxpos;
pos = GetScrollPos();
GetScrollRange(Minpos,Maxpos);
switch( nSBCode )
{
case SB_LINEUP:
if( pos > *Minpos )
pos -= INT_SBLINEUP;
break;
case SB_LINEDOWN:
if( pos < *Maxpos )
pos += INT_SBLINEDOWN;
break;
case SB_PAGEUP:
if( pos-INT_SBPAGEUP > *Minpos )
pos -= INT_SBPAGEUP;
else
pos = *Minpos;
break;
case SB_PAGEDOWN:
if( pos+INT_SBPAGEDOWN < *Maxpos )
pos += INT_SBPAGEDOWN;
else
pos = *Maxpos;
break;
case SB_THUMBPOSITION:
pos = nPos;
break;
}
SetScrollPos(pos,TRUE);
CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);
}
编译运行后,单击滚动条发现没有任何反应;在上面的函数上加断点,调试发现触发WM_VSCROLL消息后,根本没有调用这个函数。那么如何让CMyScrollBar类控件对象自己处理“WM_VSCROLL”消息呢?请看“第e步”。
e.为CMyScrollBar类添加"=WM_VSCROLL"消息(这个消息是反射消息)响应函数 (通过类视图,右键单击类名|Add Windows Message Handler....,用ClassWizard也行)
[cpp] view plain copy
void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
{
// TODO: Add your message handler code here
int pos,Minpos=0,Maxpos=100;
pos = GetScrollPos();
GetScrollRange(&Minpos,&Maxpos);
switch( nSBCode )
{
case SB_LINEUP:
if( pos > Minpos )
pos -= INT_SBLINEUP;
break;
case SB_LINEDOWN:
if( pos < Maxpos )
pos += INT_SBLINEDOWN;
break;
case SB_PAGEUP:
if( pos-INT_SBPAGEUP > Minpos )
pos -= INT_SBPAGEUP;
else
pos = Minpos;
break;
case SB_PAGEDOWN:
if( pos+INT_SBPAGEDOWN < Maxpos )
pos += INT_SBPAGEDOWN;
else
pos = Maxpos;
break;
case SB_THUMBPOSITION:
pos = nPos;
break;
}
SetScrollPos(pos,TRUE);
}
运行后发现垂直滚动条可以很好的运行;调试发现,触发WM_VSCROLL消息后,会跳到下面这个函数中
[cpp] view plain copy
CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
总结:两个消息的宏声明不一样
[cpp] view plain copy
BEGIN_MESSAGE_MAP(CMyScrollBar, CScrollBar)
//{{AFX_MSG_MAP(CMyScrollBar)
ON_WM_VSCROLL() //普通消息
ON_WM_VSCROLL_REFLECT() //反射消息,由控件自身处理
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
f. 在MyDialog.h中添加垂直滚动条,绑定一个变量
CMyScrollBar m_srcrolbar;
g. 在CMyDialog中OnInitDialog函数中初始化上面的变量
[cpp] view plain copy
int i_scroMax = 100;
m_scrolbar.SetScrollRange(0,i_scroMax);
m_scrolbar.SetScrollPos(50);
h. 在CMyDialog类中响应WM_VSROLL消息响应
[cpp] view plain copy
void CMyDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
int pos,Minpos=0,Maxpos=0;
pos = m_scrolbar.GetScrollPos();
m_scrolbar.GetScrollRange(&Minpos,&Maxpos);
switch( nSBCode )
{
case SB_LINEUP:
if( pos > Minpos )
pos -= INT_SBLINEUP;
break;
case SB_LINEDOWN:
if( pos < Maxpos )
pos += INT_SBLINEDOWN;
break;
case SB_PAGEUP:
if( pos-INT_SBPAGEUP > Minpos )
pos -= INT_SBPAGEUP;
else
pos = Minpos;
break;
case SB_PAGEDOWN:
if( pos+INT_SBPAGEDOWN < Maxpos )
pos += INT_SBPAGEDOWN;
else
pos = Maxpos;
break;
case SB_THUMBPOSITION:
pos = nPos;
break;
}
m_scrolbar.SetScrollPos(pos,TRUE);
CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}
运行发现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
//Mark:20131215
void CFatherDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if( pScrollBar->GetDlgCtrlID() == m_Vscrollbar.GetDlgCtrlID()) //如果消息对应的控件ID号是我要处理的控件则进行对应处理
{
m_Vscrollbar.OnVScroll(nSBCode,nPos,pScrollBar);
}
//这样就可以针对控件的ID号分别控制多个垂直滚动条,而达到互不干扰、代码思路清晰的好处
CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}
注意:上面的m_Vscrollbar对象的OnVscroll函数一定要声明成public访问权限,用ClassWizard添加的是Protected访问权限,可以自己手动改过来。
3、总结
如果要控件对应的对象自己处理一个消息,那么控件类自己必须实现“=WM_XXXX”反射响应函数;如果让控件的拥有者相对应的对象处理这个消息,那么应该在改对象的类中实现“WM_XXX”普通响应函数,并针对这个控件绑定的对象设计代码。
http://blog.csdn.net/qq2399431200/article/details/17336455
所谓消息反射就是控件拥有者自己不处这个理消息,而是反射给控件对象本身来处理这个消息
1、“=WM_VSCROLL”是消息反射标志 , WM_VSCROLL是 消息响应的标志,在VC6.0的ClassWizard中注意会发现这两个不同的消息,VS2010中没有“=WM_VSCROLL”,但是可以通过手动添加:
消息映射宏声明:
[cpp] view plain copy
BEGIN_MESSAGE_MAP(CMyScrollBar, CScrollBar)
//{{AFX_MSG_MAP(CMyScrollBar)
ON_WM_VSCROLL() //普通消息
ON_WM_VSCROLL_REFLECT() //反射消息,由控件自身处理
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
消息响应函数
[cpp] view plain copy
//响应“WM_VSCROLL”消息
void CMyScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);
}
//响应“=WM_VSCROLL”消息
void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
{
// TODO: Add your message handler code here
}
注意:上面两个“TODO”的内容是有区别的
2、以MFC基于对话框工程来讲解:
a. CMyDialog,CMyApp,然后添加一个CMyScrollBar:public CScrollBar类
b. 在MyDialog.h中添加垂直滚动条,绑定一个变量
CMyScrollBar m_Vsrcrollbar;
c. 在CMyDialog中OnInitDialog函数中初始化上面的变量
[cpp] view plain copy
//初始化垂直滚动条
int i_scroMax = 100;
m_Vscrollbar.SetScrollRange(0,i_scroMax);
m_Vscrollbar.SetScrollPos(50);
d. 为CMyScrollBar类添加"WM_VSCROLL"消息(这个消息是反射消息)响应函数 (通过ClassWiard)
[cpp] view plain copy
#define INT_SBLINEUP 4
#define INT_SBLINEDOWN 4
#define INT_SBPAGEUP 25
#define INT_SBPAGEDOWN 25 //下面所有代码都会使用
void CMyScrollBar::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
int pos,*Minpos,*Maxpos;
pos = GetScrollPos();
GetScrollRange(Minpos,Maxpos);
switch( nSBCode )
{
case SB_LINEUP:
if( pos > *Minpos )
pos -= INT_SBLINEUP;
break;
case SB_LINEDOWN:
if( pos < *Maxpos )
pos += INT_SBLINEDOWN;
break;
case SB_PAGEUP:
if( pos-INT_SBPAGEUP > *Minpos )
pos -= INT_SBPAGEUP;
else
pos = *Minpos;
break;
case SB_PAGEDOWN:
if( pos+INT_SBPAGEDOWN < *Maxpos )
pos += INT_SBPAGEDOWN;
else
pos = *Maxpos;
break;
case SB_THUMBPOSITION:
pos = nPos;
break;
}
SetScrollPos(pos,TRUE);
CScrollBar::OnVScroll(nSBCode, nPos, pScrollBar);
}
编译运行后,单击滚动条发现没有任何反应;在上面的函数上加断点,调试发现触发WM_VSCROLL消息后,根本没有调用这个函数。那么如何让CMyScrollBar类控件对象自己处理“WM_VSCROLL”消息呢?请看“第e步”。
e.为CMyScrollBar类添加"=WM_VSCROLL"消息(这个消息是反射消息)响应函数 (通过类视图,右键单击类名|Add Windows Message Handler....,用ClassWizard也行)
[cpp] view plain copy
void CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
{
// TODO: Add your message handler code here
int pos,Minpos=0,Maxpos=100;
pos = GetScrollPos();
GetScrollRange(&Minpos,&Maxpos);
switch( nSBCode )
{
case SB_LINEUP:
if( pos > Minpos )
pos -= INT_SBLINEUP;
break;
case SB_LINEDOWN:
if( pos < Maxpos )
pos += INT_SBLINEDOWN;
break;
case SB_PAGEUP:
if( pos-INT_SBPAGEUP > Minpos )
pos -= INT_SBPAGEUP;
else
pos = Minpos;
break;
case SB_PAGEDOWN:
if( pos+INT_SBPAGEDOWN < Maxpos )
pos += INT_SBPAGEDOWN;
else
pos = Maxpos;
break;
case SB_THUMBPOSITION:
pos = nPos;
break;
}
SetScrollPos(pos,TRUE);
}
运行后发现垂直滚动条可以很好的运行;调试发现,触发WM_VSCROLL消息后,会跳到下面这个函数中
[cpp] view plain copy
CMyScrollBar::VScroll(UINT nSBCode, UINT nPos)
总结:两个消息的宏声明不一样
[cpp] view plain copy
BEGIN_MESSAGE_MAP(CMyScrollBar, CScrollBar)
//{{AFX_MSG_MAP(CMyScrollBar)
ON_WM_VSCROLL() //普通消息
ON_WM_VSCROLL_REFLECT() //反射消息,由控件自身处理
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
f. 在MyDialog.h中添加垂直滚动条,绑定一个变量
CMyScrollBar m_srcrolbar;
g. 在CMyDialog中OnInitDialog函数中初始化上面的变量
[cpp] view plain copy
int i_scroMax = 100;
m_scrolbar.SetScrollRange(0,i_scroMax);
m_scrolbar.SetScrollPos(50);
h. 在CMyDialog类中响应WM_VSROLL消息响应
[cpp] view plain copy
void CMyDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
int pos,Minpos=0,Maxpos=0;
pos = m_scrolbar.GetScrollPos();
m_scrolbar.GetScrollRange(&Minpos,&Maxpos);
switch( nSBCode )
{
case SB_LINEUP:
if( pos > Minpos )
pos -= INT_SBLINEUP;
break;
case SB_LINEDOWN:
if( pos < Maxpos )
pos += INT_SBLINEDOWN;
break;
case SB_PAGEUP:
if( pos-INT_SBPAGEUP > Minpos )
pos -= INT_SBPAGEUP;
else
pos = Minpos;
break;
case SB_PAGEDOWN:
if( pos+INT_SBPAGEDOWN < Maxpos )
pos += INT_SBPAGEDOWN;
else
pos = Maxpos;
break;
case SB_THUMBPOSITION:
pos = nPos;
break;
}
m_scrolbar.SetScrollPos(pos,TRUE);
CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}
运行发现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
//Mark:20131215
void CFatherDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if( pScrollBar->GetDlgCtrlID() == m_Vscrollbar.GetDlgCtrlID()) //如果消息对应的控件ID号是我要处理的控件则进行对应处理
{
m_Vscrollbar.OnVScroll(nSBCode,nPos,pScrollBar);
}
//这样就可以针对控件的ID号分别控制多个垂直滚动条,而达到互不干扰、代码思路清晰的好处
CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}
注意:上面的m_Vscrollbar对象的OnVscroll函数一定要声明成public访问权限,用ClassWizard添加的是Protected访问权限,可以自己手动改过来。
3、总结
如果要控件对应的对象自己处理一个消息,那么控件类自己必须实现“=WM_XXXX”反射响应函数;如果让控件的拥有者相对应的对象处理这个消息,那么应该在改对象的类中实现“WM_XXX”普通响应函数,并针对这个控件绑定的对象设计代码。
http://blog.csdn.net/qq2399431200/article/details/17336455
相关文章推荐
- =WM_VSCROLL(消息反射) 和 WM_VSCROLL(消息响应)的区别
- WM_CREATE和WM_INITDIALOG消息响应函数之区别,以及MFC应用程序中处理消息的...
- WM_CREATE和WM_INITDIALOG消息响应函数之区别,以及MFC应用程序中处理消息的
- WM_CREATE和WM_INITDIALOG消息响应函数之区别,以及MFC应用程序中处理消息的...
- Windows的自带控件(比如TButton)大多数消息都由它自己处理,Delphi覆盖了那么多WM_函数优先级较低,一般用不上
- 消息响应COMMAND 和 UPDATE_COMMAND_UI的区别,使用范围的区别,使用对象的区别,等等方面的。
- WM_CREATE消息响应函数和WM_INITDIALOG消息响应函数之区别
- 091111(星期三)控件会处理自己的消息
- Edit 控件响应或处理 回车消息
- QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象 good
- ios 中调用函数的方法是消息传递,这个和普通的函数调用的区别是,你可以随时对一个对象传递任何消息,而不需要在编译的时候声明这些方法。所以Objective-C可以在runtime的时候
- 输出流实际上不写对象的值,而是对象吧自己本身写在流上
- 有几个控件的操作时有关联关系,一个对话框中有多组这样的控件群,各个组中的控件的消息响应处理非常类似,以下提供解决方案
- 关于模态/非模态对话框不响应菜单的UPDATE_COMMAND_UI消息(对对WM_INITMENUPOPUP消息的处理)
- 对话框中添加控件时,CMyDialog类中并没有CButton类的对象,却可以响应鼠标消息,为什么?
- 使用SendMessage方法对窗体上的控件进行截图,该方法的思想就是把控件的句柄拿到,对控件发送WM_PAINT消息,并且把希望得到图形对象的句柄当作wParam参数传过去,这样就可以在图形对象得到想要得图形。
- 一步一步实现自己的模拟控件(9)——消息处理
- 详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息
- WM_CREATE消息响应函数和WM_INITDIALOG消息响应函数之区别
- C++自定义ClistCtrl控件响应数据项的点击事件&&消息反射的原理