Scrollbar控件的认识

关于scrollbar只研究上下滚动

1. 首先Scrollbar的父窗口是ContainerUI,不管哪个控件想使用滚动条,该空间必须是Container或者继承Container.

2. 该函数记录滚动条的百分比的数值是m_nScrollPos,然后记录滚动条总共被分成多少份的则是m_nRange。

3、滚动条有四个关键的图标:button1、button2、thumb、rail.其中这两个按钮是两端的两个按钮,thumb则是整个滑动的按钮,而rail则是整个滑动按钮中间的小按钮,这两个按钮的位置都是通过动态计算获取到的。具体的thumb计算是在SetPos函数,而rail按钮则是通过thumb的位置来确定,直接在PaintRail的时候进行计算显示即可。

4、thumb的大小则是通过在第479行:int cyThumb = cy * (rc.bottom - rc.top) / (m_nRange + rc.bottom - rc.top);计算出来的,也就是说如果m_nRange越大的话则thumb相对整个滚动条就越小。

5、当整个滚动条的大小:button1高度+button2高度<m_cxyFixed.cy+m_cxyFixed.cy(这里是两个按钮均可见)的时候则thumb滚动条不显示第519行:::ZeroMemory(&m_rcThumb, sizeof(m_rcThumb));把滚动条的大小分给button1和button2。

6、然后doevent中如果点击button1或者button2的时候则会触发containerui的linedown或者up然后可以看containerui中的linedown函数,linesize是固定大小的8,而滚动条则是默认大小的十六,但是这个没关系,因为当点击linedown或者up的时候,位置大小的修改时依赖containerui的移动位置来修改的。

scrollbar的第551行
if( m_pOwner != NULL ) m_pOwner->LineUp(); 
                    else SetScrollPos(m_nScrollPos - m_nLineSize);

// 也就是说当有容器的时候本身不会去设置scrollpos而是通过containerui来设置大小。
View Code

然后这里看containerui的相关lineup函数

    void CContainerUI::LineUp()
    {
        int cyLine = 8;
        if( m_pManager ) cyLine = m_pManager->GetDefaultFontInfo()->tm.tmHeight + 8;

        SIZE sz = GetScrollPos();
        sz.cy -= cyLine;
        SetScrollPos(sz);
    }
//这里明确表明了linesize大小为8



// 而这里的setscrollpos函数则做了两件事:1、调用scrollbar的setscrollpos函数。    2、将自身的elements向上移动相应的像素。

    void CContainerUI::SetScrollPos(SIZE szPos)
    {
        int cx = 0;
        int cy = 0;
        if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {
            int iLastScrollPos = m_pVerticalScrollBar->GetScrollPos();
            m_pVerticalScrollBar->SetScrollPos(szPos.cy);
            cy = m_pVerticalScrollBar->GetScrollPos() - iLastScrollPos;
        }

        if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {
            int iLastScrollPos = m_pHorizontalScrollBar->GetScrollPos();
            m_pHorizontalScrollBar->SetScrollPos(szPos.cx);
            cx = m_pHorizontalScrollBar->GetScrollPos() - iLastScrollPos;
        }

        if( cx == 0 && cy == 0 ) return;

        RECT rcPos;
        for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {
            CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);
            if( !pControl->IsVisible() ) continue;
            if( pControl->IsFloat() ) continue;

            rcPos = pControl->GetPos();
            rcPos.left -= cx;
            rcPos.right -= cx;
            rcPos.top -= cy;
            rcPos.bottom -= cy;
            pControl->SetPos(rcPos);
        }

        Invalidate();
    }
View Code

同样的pageup跟pagedown也是通过contaierui函数来设定的。

但是这里滚动的大小并不是固定大小而是一页的大小

void CContainerUI::PageUp()
    {
        SIZE sz = GetScrollPos();
        int iOffset = m_rcItem.bottom - m_rcItem.top - m_rcInset.top - m_rcInset.bottom;
        if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) iOffset -= m_pHorizontalScrollBar->GetFixedHeight();
        sz.cy -= iOffset;
        SetScrollPos(sz);
    }
View Code

7、这里的uiscrollbar的第546行的settimer是为了在长按pageup或down(lineup跟down也是一样)时触发移动,或者拖动滚动条的时候触发的移动。具体可以看doevent函数。的第660行开始的if( event.Type == UIEVENT_TIMER && event.wParam == DEFAULT_TIMERID )

原文地址:https://www.cnblogs.com/cxiaoln/p/4395481.html