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);
}

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

发布了16 篇原创文章 · 获赞 21 · 访问量 14万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览