MFC CScrollView鼠标拖拽移动滚动条出现回滚问题

MFC 专栏收录该内容
6 篇文章 0 订阅

MFC CScrollView鼠标拖拽移动滚动条出现回滚问题

问题分析:逻辑视图较大的时候(10w),使用鼠标拖拽移动滚动条时(单击不会回滚),会在32000左右回滚到0。看到熟悉的32000,应该是在获取滚动条位置时,出现了短字节数据转换到长字节数据时出现的精度丢失问题,通过debug单步调试,发现函数调用层次如下:滚动条位置nPos数据,通过函数一层层的转换和计算后传递到SetScrollPos正式更新滚动条位置。

OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) (垂直方向移动滚动条时调用)

       OnScroll(MAKEWORD(nSBCode, 0xff), nPos);

              OnScrollBy(CSize(x - xOrig, y - yOrig), bDoScroll);

                       SetScrollPos(SB_HORZ, x);(此处更新滚动条位置)

通过打印nPos,当x为0后(回滚后),nPos是一个很大的数0xff280012,所以很有可能是OnHScroll上一层函数将nPos传递到OnHScroll出现问题。查找调用OnHScroll的函数,在wincore.cpp以下函数调用OnHScroll

case AfxSig_SCROLL_REFLECT:
	{
		// special case for WM_VSCROLL and WM_HSCROLL
		ASSERT(message == WM_VSCROLL || message == WM_HSCROLL 
                || message == WM_VSCROLL+WM_REFLECT_BASE 
                || message == WM_HSCROLL+WM_REFLECT_BASE);
		int nScrollCode = (short)LOWORD(wParam);
		int nPos = (short)HIWORD(wParam);   // nPos是short转换的,即不能大于32768
		if (lpEntry->nSig == AfxSig_SCROLL)
			(this->*mmf.pfn_v_u_u_W)(nScrollCode, nPos,
				CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
		else
			(this->*mmf.pfn_v_u_u)(nScrollCode, nPos);
	}
	break;

可以看到,其中nPos,是short到int转换成的;因为某种原因,short溢出了,变成了负数,传输到OnHScroll后,再次转换成UINT,所以出现了一个很大的数0xff280012。

解决方式:抛开在wincore.cpp调用OnHScroll函数,直接获取滚动条的位置进行更新;在OnHScroll使用GetScrollInfo();函数直接获取滚动条位置,传递下去。


void MyScrollView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    SCROLLINFO si;
    GetScrollInfo(SB_HORZ,&si);
    CScrollView::OnHScroll(nSBCode, si.nTrackPos, pScrollBar);
}

 

 

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值