MFC中Cwnd窗口添加滚动条
http://blog.youkuaiyun.com/chaozi2008/article/details/8116449
最近一个项目需要用到从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;
- }
这时候你会发现,滑块大小是固定的,就是那么大,而且拖动后松开鼠标就回到开始的位置了。怎么会这样呢?嘿嘿,原来Windows自己是不会自动改变滑块位置的,需要程序自己去设置滑块的位置,这就是第二步。
第二:设置滑块位置。这里需要在对应的响应函数中添加处理代码,以水平滚动条为例:
- void CAtrributeWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
-
-
- static int oldpos = 0;
- int minpos = 0;
- int maxpos = 0;
- GetScrollRange(SB_HORZ, &minpos, &maxpos);
- maxpos = GetScrollLimit(SB_HORZ);
-
-
- int curpos = GetScrollPos(SB_HORZ);
-
-
- switch (nSBCode)
- {
- case SB_LEFT:
- curpos = minpos;
- break;
-
- case SB_RIGHT:
- curpos = maxpos;
- break;
-
- case SB_ENDSCROLL:
- break;
-
- case SB_LINELEFT:
- if (curpos > minpos)
- curpos--;
- break;
-
- case SB_LINERIGHT:
- if (curpos < maxpos)
- curpos++;
- break;
-
- case SB_PAGELEFT:
- {
-
- SCROLLINFO info;
- GetScrollInfo(SB_HORZ, &info, SIF_ALL);
-
- if (curpos > minpos)
- curpos = max(minpos, curpos - (int) info.nPage);
- }
- break;
-
- case SB_PAGERIGHT:
- {
-
- SCROLLINFO info;
- GetScrollInfo(SB_HORZ, &info, SIF_ALL);
-
- if (curpos < maxpos)
- curpos = min(maxpos, curpos + (int) info.nPage);
- }
- break;
-
- case SB_THUMBPOSITION:
- curpos = nPos;
- break;
-
- case SB_THUMBTRACK:
- curpos = nPos;
- break;
- }
-
-
- 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;
- 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);
- }
现在看看是不是达到预期的要求了呢!!