Bootstrap

MFC开发,给对话框添加垂直滚动条并解决鼠标滚动响应的问题

无论在使用QT或者MFC进行界面开发时,都会出现在一个对话框里面存在好多的选项,导致对话框变得非常长或者非常大,就会显现的不美观,在这种情况下通常是添加一个页面的滚动条来解决这个问题,下面我们就来介绍给MFC的对话框添加滚动条和响应鼠标滚轮滚动的事件

在写下面的代码之前需要现在对话框的OnInitDialog()函数中将窗口大小和滚动条长度进行初始化

// 初始化窗口大小
CRect rect;
GetWindowRect(&rect);
TRACE(_T("width:%d height:%d\n"), rect.Width(), rect.Height());
rect.bottom = rect.top + 250;
SetWindowPos(NULL, rect.left, rect.top, 810, 450, SWP_NOZORDER | SWP_NOMOVE);
// 初始化滚动条大小
SCROLLINFO scrollinfo;
GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
scrollinfo.nPage = 10;
scrollinfo.nMax = 72;
SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);

给对话框添加滚动条

首先给对话框添加垂直滚动条

点开对话框设计页面→点击属性→将垂直滚动条设置为True

添加垂直滚动条的消息处理函数

右键点击类向导→选择消息→点击添加WM_VSCROLL消息处理程序

在消息处理函数中添加下面的代码,即可实现对话框滚动条滚动

void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO scrollinfo;
	GetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
	int unit = 3;
	scrollinfo.nPage = 10;
	switch (nSBCode)
	{
	case SB_LINEUP:          // 向上滚动一行
		scrollinfo.nPos -= 1;
		if (scrollinfo.nPos < scrollinfo.nMin)
		{
			scrollinfo.nPos = scrollinfo.nMin;
			break;
		}
		SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
		ScrollWindow(0, unit);
		break;
	case SB_LINEDOWN:           // 向下滚动一行
		scrollinfo.nPos += 1;
		if (scrollinfo.nPos + scrollinfo.nPage > scrollinfo.nMax)  //此处一定要注意加上滑块的长度,再作判断
		{
			scrollinfo.nPos = scrollinfo.nMax;
			break;
		}
		SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
		ScrollWindow(0, -unit);
		break;
	case SB_PAGEUP:            // 向上滚动一页
		scrollinfo.nPos -= 5;
		if (scrollinfo.nPos < scrollinfo.nMin)
		{
			scrollinfo.nPos = scrollinfo.nMin;
			break;
		}
		SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
		ScrollWindow(0, unit * 5);
		break;
	case SB_PAGEDOWN:        // 向下滚动一页
		scrollinfo.nPos += 5;
		if (scrollinfo.nPos  > (scrollinfo.nMax - scrollinfo.nPage))  //此处一定要注意加上滑块的长度,再作判断
		{
			scrollinfo.nPage = 13;
			SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
			break;
		}
		SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
		ScrollWindow(0, -unit * 5);
		break;
	case SB_ENDSCROLL:      // 结束滚动
		break;
	case SB_THUMBPOSITION:  // 滚动到绝对位置。当前位置在nPos中提供
		break;
	case SB_THUMBTRACK:     // 将滚动框拖到指定位置。当前位置在nPos中提供
		ScrollWindow(0, (scrollinfo.nPos - nPos) * unit);
		scrollinfo.nPos = nPos;
		SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
		break;
	}
	CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

效果展示

响应鼠标滚轮滚动事件

虽然上面的方式实现了对话框页面的滚动效果,但是使用起来依然是不太方便,通常一个页面带有滚动条,这个页面通过鼠标滑动也是可以进行页面滚动的,但是如果只是单单实现了上面的代码,还是达不到我们想要的效果的,这时就需要对鼠标的滚动事件进行进一步的处理

添加鼠标滚动事件处理程序

右键点击类向导→选择消息→点击添加WM_MOUSEWHEEL消息处理程序

在消息处理函数中添加下面的代码,即可实现对话框鼠标滚轮滚动

在鼠标滚动的处理函数中直接调用我们写好的滚动条处理事件即可

BOOL CSettingDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{	
	SCROLLINFO scrollinfo;
	GetScrollInfo(SB_VERT, &scrollinfo);
	if (zDelta == 120)
	{
		OnVScroll(SB_PAGEUP, GetScrollPos(SB_VERT), GetScrollBarCtrl(SB_VERT));
	}
	else if (zDelta == -120)
	{
		OnVScroll(SB_PAGEDOWN, GetScrollPos(SB_VERT), GetScrollBarCtrl(SB_VERT));
	}
	return CDialog::OnMouseWheel(nFlags, zDelta, pt);
}

效果展示

在实现中出现的问题和解决方法

出现的问题:如果在界面的底部不停通过鼠标进行滚动就会出现页面不对或偏移的问题,这个问题的原因是由于滚动条的最下面还有一点空余,之前发现这个问题的解决方法是不移动页面就直接将滚动条向下移,这样就导致了这个问题的出现

问题分析:这个问题的主要原因就是滚动条的长度和页面的长度不匹配导致的问题,但是谁也不能将页面和滚动条的长度进行完全的匹配,最后参考其他应用软件找到了他们处理这个问题的方法,于是运用到了我的这个项目上,把问题解决了

解决方法:解决方法是,当滑动到底部时不改变滚动条的位置,而是修改滚动条的长度来解决这个问题

OnVScroll函数代码的SB_PAGEDOWN分支就是基于这种方式实现的

case SB_PAGEDOWN:
    scrollinfo.nPos += 5;
    if (scrollinfo.nPos  > (scrollinfo.nMax - (int)scrollinfo.nPage))  //此处一定要注意加上滑块的长度,再作判断
    {
        // 不移动页面,只是将滚动条的长度增加
        scrollinfo.nPage = 13;
        SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
        break;
    }
    SetScrollInfo(SB_VERT, &scrollinfo, SIF_ALL);
    ScrollWindow(0, -unit * 5);
    break;

通过这个方法就可以解决这个小小的细节问题,这里可以不增加长度直接不移动也是可以的,但是看着就不是那么完美了

到这里,给对话框添加垂直滚动条并响应鼠标滚动事件是页面移动就介绍完了

感谢观看学习,大佬们多多指点,愿明天的自己会感谢当下的努力!!!!

;