自定义控件滚动条操作(二)

本文详细介绍了如何在MFC中为自定义控件添加滚动条响应,包括定义滚动条位置设置函数,重载垂直和水平滚动条的响应函数,以及实现鼠标滚轮滚动垂直滚动条的功能。同时,解析了CWnd::SetScrollInfo的使用,强调了通过CScrollBar管理滚动条的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

五. 滚动条的响应代码


控件上添加了滚动条, 只是让滚动条显示, 但没有响应. 响应就是你点击滚动条时, 根据滚动条的位置, 显示对应内容, 并且你需要设置滚动条的位置.

所以响应函数需要做两件事情:

A. 设置滚动条到响应位置.(如果需要);

B. 根据滚动条的响应位置设置要显示的内容的位置.


 

5.1 定义滚动条位置设置函数

void CMyCtrl::SetScrollBarsPos(int nScrollBar, int nPos)
{
	SCROLLINFO siSet;
	siSet.cbSize = sizeof(SCROLLINFO);
	siSet.fMask = SIF_POS;
	siSet.nPos = nPos;
	SetScrollInfo(nScrollBar, &siSet, true);
}

 

5.2 重载垂直滚动条响应函数

void CMyCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// 获取滚动条最新位置
	SCROLLINFO siGet;
	siGet.cbSize = sizeof(SCROLLINFO);
	GetScrollInfo(SB_VERT, &siGet, SIF_TRACKPOS | SIF_POS | SIF_RANGE | SIF_PAGE);

	switch(nSBCode)
	{
    case SB_THUMBPOSITION:	// 拖动滚动块时产生的事件
    case SB_THUMBTRACK:
		{
			// siGet.nTrackPos就是滚动条最新位置
			// 设置滚动条最新位置
			SetScrollBarsPos(SB_VERT, siGet.nTrackPos);
			// 根据siGet.nTrackPos计算你的内容的显示位置, 并记录.
			// 这个内容的显示位置, 在你绘制控件的时候会用到.
			// 怎么计算, 你自己定
			...
			}
		}
		break;
    case SB_LINEDOWN:	// 点击垂直滚动条"下箭头"产生的事件
	case SB_PAGEDOWN:	// 点击"滚动块"与"下箭头"之间的"空白处"产生的事件
		{
			// 计算滚动条的最新位置
			int nNewPos = siGet.nPos + 偏移值;	// 偏移值是多少, 你自己定
			// 设置滚动条最新位置
			SetScrollBarsPos(SB_VERT, nNewPos);
			// 根据siGet.nTrackPos计算你的内容的显示位置, 并记录.
			// 这个内容的显示位置, 在你绘制控件的时候会用到.
			// 怎么计算, 你自己定
			...
		}
        break;
    case SB_LINEUP:		// 点击垂直滚动条"上箭头"产生的事件
	case SB_PAGEUP:		// 点击"滚动块"与"上箭头"之间的"空白处"产生的事件
		{
			// 计算滚动条的最新位置
			int nNewPos = siGet.nPos - 偏移值;	// 偏移值是多少, 你自己定
			// 设置滚动条最新位置
			SetScrollBarsPos(SB_VERT, nNewPos);
			// 根据siGet.nTrackPos计算你的内容的显示位置, 并记录.
			// 这个内容的显示位置, 在你绘制控件的时候会用到.
			// 怎么计算, 你自己定
			...
		}
        break;
	case SB_TOP:		// 跳到最顶
		{
			if(0 == siGet.nPos)
			{
				break;
			}
			else
			{
				SetScrollBarsPos(SB_VERT, 0);
			}
		}
        break;
	case SB_BOTTOM:		// 跳到最底
		{
			if(siGet.nMax - siGet.nPage + 1 == siGet.nPos)
			{
				break;
			}
			else
			{
				SetScrollBarsPos(SB_VERT, siGet.nMax - siGet.nPage + 1);
			}
		}
        break;
	}
}	

   

 

5.3 重载水平滚动条响应函数

void CMyCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO siGet;
	siGet.cbSize = sizeof(SCROLLINFO);
	GetScrollInfo(SB_HORZ, &siGet, SIF_TRACKPOS | SIF_POS | SIF_RANGE | SIF_PAGE);

	switch(nSBCode)
	{
    case SB_THUMBPOSITION:	// 拖动滚动块时产生的事件
    case SB_THUMBTRACK:
		{
			// siGet.nTrackPos就是滚动条最新位置
			// 设置滚动条最新位置
			SetScrollBarsPos(SB_HORZ, siGet.nTrackPos);
			// 根据siGet.nTrackPos计算你的内容的显示位置, 并记录.
			// 这个内容的显示位置, 在你绘制控件的时候会用到.
			// 怎么计算, 你自己定
			...
			}
		}
		break;
    case SB_LINERIGHT:	// 点击水平滚动条"右箭头"产生的事件
	case SB_PAGERIGHT:	// 点击"滚动块"与"右箭头"之间的"空白处"产生的事件
		{
			// 计算滚动条的最新位置
			int nNewPos = siGet.nPos + 偏移值;	// 偏移值是多少, 你自己定
			// 设置滚动条最新位置
			SetScrollBarsPos(SB_HORZ, nNewPos);
			// 根据siGet.nTrackPos计算你的内容的显示位置, 并记录.
			// 这个内容的显示位置, 在你绘制控件的时候会用到.
			// 怎么计算, 你自己定
			...
		}
        break;
    case SB_LINELEFT:		// 点击垂直滚动条"左箭头"产生的事件
	case SB_PAGELEFT:		// 点击"滚动块"与"左箭头"之间的"空白处"产生的事件
		{
			// 计算滚动条的最新位置
			int nNewPos = siGet.nPos - 偏移值;	// 偏移值是多少, 你自己定
			// 设置滚动条最新位置
			SetScrollBarsPos(SB_HORZ, nNewPos);
			// 根据siGet.nTrackPos计算你的内容的显示位置, 并记录.
			// 这个内容的显示位置, 在你绘制控件的时候会用到.
			// 怎么计算, 你自己定
			...
		}
        break;
	case SB_LEFT:		// 跳到最左
		{
			if(0 == siGet.nPos)
			{
				break;
			}
			else
			{
				SetScrollBarsPos(SB_HORZ, 0);
			}
		}
        break;
	case SB_RIGHT:		// 跳到最右
		{
			if(siGet.nMax - siGet.nPage + 1 == siGet.nPos)
			{
				break;
			}
			else
			{
				SetScrollBarsPos(SB_HORZ, siGet.nMax - siGet.nPage + 1);
			}
		}
        break;
	}
}

 

5.4 鼠标滚轮滚动垂直滚动条


重载OnMouseWheel函数, 在函数内向垂直滚动条发消息即可

BOOL CMyCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	if(zDelta > 0)
	{
		 PostMessage(WM_VSCROLL, SB_LINEUP, 0);
	}
	else
	{
		PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
	}
    return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

 

 

六. CWnd::SetScrollInfo的理解

BOOL CWnd::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw)
{
	ASSERT(lpScrollInfo != NULL);

	HWND hWnd = m_hWnd;
	CScrollBar* pScrollBar;
	if (nBar != SB_CTL && (pScrollBar = GetScrollBarCtrl(nBar)) != NULL)
	{
		hWnd = pScrollBar->m_hWnd;
		nBar = SB_CTL;
	}
	lpScrollInfo->cbSize = sizeof(*lpScrollInfo);
	::SetScrollInfo(hWnd, nBar, lpScrollInfo, bRedraw);
	return TRUE;
}
这是CWnd::SetScrollInfo, 在里面有一个GetScrollBarCtrl调用
CScrollBar* CWnd::GetScrollBarCtrl(int) const
{
	return NULL;        // no special scrollers supported
}

 

个人理解: 你的可以使用CScrollBar添加到你的自定义控件, 然后用CScrollBar来管理你的所有与滚动条相关的东西. 此时, 你需要重载GetScrollBarCtrl函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值