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的移动位置来修改的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
scrollbar的第551行 if( m_pOwner != NULL ) m_pOwner->LineUp(); else SetScrollPos(m_nScrollPos - m_nLineSize); // 也就是说当有容器的时候本身不会去设置scrollpos而是通过containerui来设置大小。
然后这里看containerui的相关lineup函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); }
同样的pageup跟pagedown也是通过contaierui函数来设定的。
但是这里滚动的大小并不是固定大小而是一页的大小
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); }
7、这里的uiscrollbar的第546行的settimer是为了在长按pageup或down(lineup跟down也是一样)时触发移动,或者拖动滚动条的时候触发的移动。具体可以看doevent函数。的第660行开始的if( event.Type == UIEVENT_TIMER && event.wParam == DEFAULT_TIMERID )