最近一个项目需要用到从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);
}
现在看看是不是达到预期的要求了呢!!