您的位置:首页 > 其它

=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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐