MFC中Cwnd窗口添加滚动条

最近一个项目需要用到从CWnd派生的窗口添加滚动条,自己上网查过好多资料,但都没有很明确的说明这个应该怎么做,经过自己的摸索和努力,终于给完成了。在这里分享一下我的方法:

第一:设置窗口属性。首先,Cwnd是自带有滚动条属性的,在create时加上WS_HSCROLL| WS_VSCROLL风格,则创建出的窗口就会带有滚动条了。

if (!m_AttributeWnd.Create (NULL,NULL,WS_TABSTOP | WS_CHILD | WS_HSCROLL| WS_VSCROLL ,rect, this,12331))
	{
		TRACE0("Failed to create wndAttri wnd\n");
		return;      // fail to create
	}

这时候你会发现,滑块大小是固定的,就是那么大,而且拖动后松开鼠标就回到开始的位置了。怎么会这样呢?嘿嘿,原来Windows自己是不会自动改变滑块位置的,需要程序自己去设置滑块的位置,这就是第二步。

第二:设置滑块位置。这里需要在对应的响应函数中添加处理代码,以水平滚动条为例:

void CAtrributeWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: Add your message handler code here and/or call default

	static int oldpos = 0;
	int minpos = 0;
	int maxpos = 0;
	GetScrollRange(SB_HORZ, &minpos, &maxpos); 
	maxpos = GetScrollLimit(SB_HORZ);

	// Get the current position of scroll box.
	int curpos = GetScrollPos(SB_HORZ);

	// Determine the new position of scroll box.
	switch (nSBCode)
	{
	case SB_LEFT:      // Scroll to far left.
		curpos = minpos;
		break;

	case SB_RIGHT:      // Scroll to far right.
		curpos = maxpos;
		break;

	case SB_ENDSCROLL:   // End scroll.
		break;

	case SB_LINELEFT:      // Scroll left.
		if (curpos > minpos)
			curpos--;
		break;

	case SB_LINERIGHT:   // Scroll right.
		if (curpos < maxpos)
			curpos++;
		break;

	case SB_PAGELEFT:    // Scroll one page left.
		{
			// Get the page size. 
			SCROLLINFO   info;
			GetScrollInfo(SB_HORZ, &info, SIF_ALL);

			if (curpos > minpos)
				curpos = max(minpos, curpos - (int) info.nPage);
		}
		break;

	case SB_PAGERIGHT:      // Scroll one page right.
		{
			// Get the page size. 
			SCROLLINFO   info;
			GetScrollInfo(SB_HORZ, &info, SIF_ALL);

			if (curpos < maxpos)
				curpos = min(maxpos, curpos + (int) info.nPage);
		}
		break;

	case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
		curpos = nPos;      // of the scroll box at the end of the drag operation.
		break;

	case SB_THUMBTRACK:   // Drag scroll box to specified position. nPos is the
		curpos = nPos;     // position that the scroll box has been dragged to.
		break;
	}

	// Set the new position of the thumb (scroll box).
	SetScrollPos(SB_HORZ, curpos);
	ScrollWindow(oldpos-curpos,0);

	oldpos = curpos;
	UpdateWindow();

	CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}
现在马上试试,是不是可以拖动滚动条了。但是新的问题出来了,滑块大小没有变化,不会像Windows中滚动条里边,滑块会随着窗口变化,窗口小滑块也变小,窗口变大,滑块也会随着变大,直到滑块消失。此时,应该如何解决这个问题呢?那就是下一步,设置滑块风格和滚动条范围。

第三:设置滚动条范围。SetScrollRange()可以完成这个操作,但是如果想要滑块跟着变化大小,这里推荐使用SetScrollInfo()函数,此函数中有个最为重要的参数为SCROLLINFO结构体,定义如下:

typedef struct tagSCROLLINFO
{
    UINT    cbSize; //设为sizeof(SCROLLINFO)
    UINT    fMask;
    int     nMin;
    int     nMax;
    UINT    nPage;
    int     nPos;
    int     nTrackPos;
}   SCROLLINFO, FAR *LPSCROLLINFO;

成员说明:
cbSize: SCROLLINFO结构长度字节数,该值在设置和查询参数时都必须填写。
fMask: 指定结构中的哪些成员是有效,该值共有如下5种选择,可以选择多种用“OR”组合起来,该值在设置和查询参数时都必须填写。
SIF_ALL      :整个结构都有效
SIF_DISABLENOSCROLL:该值仅在设定参数时使用,视控件参数设定的需要来对本结构的成员进行取舍。
SIF_PAGE      :nPage成员有效
SIF_POS      :nPos成员有效
SIF_RANGE     :nMin和nMax成员有效
nMin:滚动范围最小值
nMax:滚动范围最大值
nPage:页尺寸,用来确定比例滚动框的大小
nPos:滚动框的位置
nTrackPos:拖动时滚动框的位置,该参数只能查询,不能设置。

然后在onsize()函数中设这滚动条的大小范围:

void CAtrributeWnd::OnSize(UINT nType, int cx, int cy)
{
	CWnd::OnSize(nType, cx, cy);

	//设置滚动条范围
	SCROLLINFO si;
	si.cbSize = sizeof(si);
	si.fMask = SIF_RANGE | SIF_PAGE;
	si.nMin = 0;
	si.nMax = 998;
	si.nPage = cx;
	SetScrollInfo(SB_HORZ,&si,TRUE);
	si.nMax = 496;
	si.nPage = cy;
	SetScrollInfo(SB_VERT,&si,TRUE);

	int icurxpos = GetScrollPos(SB_HORZ);
	int icurypos = GetScrollPos(SB_VERT);
	
	if (icurxpos < m_ixoldpos || icurypos < m_iyoldpos)
	{
		ScrollWindow(m_ixoldpos-icurxpos,0);
		ScrollWindow(0,m_iyoldpos-icurypos);

	}	
	m_ixoldpos = icurxpos;
	m_iyoldpos = icurypos;

	Invalidate(TRUE);
}

现在看看是不是达到预期的要求了呢!!

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
MFC,如果我们想要在调整窗口大小时自动出现滚动条来实现内容的滚动,我们可以采取以下步骤: 1. 在需要添加滚动条的对话框或窗口类的类体添加一个CScrollView的派生类成员变量,用于处理滚动条的相关功能。例如,可以添加一个名为m_scrollView的成员变量。 2. 在对话框或窗口类的OnInitDialog(对于对话框类)或OnCreate(对于窗口类)函数,创建并初始化CScrollView对象。例如,在OnInitDialog函数可以添加如下代码: m_scrollView.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST); 3. 在对话框或窗口重写OnSize函数,用于处理窗口大小改变事件。例如,在对话框类可以添加如下代码: void CMyDialog::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); if (m_scrollView.GetSafeHwnd() != nullptr) { CRect rect; GetClientRect(rect); m_scrollView.MoveWindow(rect); } } 在窗口可以添加如下代码: void CMyWnd::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); if (m_scrollView.GetSafeHwnd() != nullptr) { CRect rect; GetClientRect(rect); m_scrollView.SetWindowPos(nullptr, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER); } } 这样,在调整窗口大小时,滚动条会根据内容的大小和窗口的大小自动进行调整,并在需要时出现或隐藏。你可以根据需要在CScrollView对象添加需要滚动的内容,例如使用CScrollView的派生类CDrawView实现自定义的绘图功能等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值