container子控件需要任意在容器中任意拖拽,就使用了绝对布局,现在要给这个container添加垂直滚动条随子控件位置的改变而改变,现在虽然拖拽和滚动条都实现了,但是当双击向下拖动子控件到一定程度(拖动时顶部有一部分未显示)滚动条以后也不会显示这部分内容了。
主要修改的代码如下:
void CContainerUI::SetPos(RECT rc)
{
if( m_pVerticalScrollBar|| m_pHorizontalScrollBar)//modify 2014-11-14
{
CControlUI::SetPos(rc);
rc = m_rcItem;
// Adjust for inset
rc.left += m_rcInset.left;
rc.top += m_rcInset.top;
rc.right -= m_rcInset.right;
rc.bottom -= m_rcInset.bottom;
if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() )
{
rc.right -= m_pVerticalScrollBar->GetFixedWidth();
}
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() )
{
rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
}
if( m_items.GetSize() == 0) {
ProcessScrollBar(rc, 0, 0);
return;
}
// Determine the minimum size
SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() )
szAvailable.cx += m_pHorizontalScrollBar->GetScrollRange();
// Place elements
int cyNeeded = 0;
int cyFixedtop = 0;
int cyFixedbottm = 0;
for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) { //modify 2014-11-14
SetFloatPos(it2);
}
//RECT rcPadding = pControl->GetPadding();//外边距在相对布局中才有效
RECT rt = pControl->GetPos();
cyFixedbottm = MAX(cyFixedbottm,rt.bottom);
cyFixedtop = MIN(cyFixedtop,rt.top);
}
cyNeeded = MAX(cyFixedbottm-cyFixedtop,szAvailable.cy);
// Process the scrollbar
ProcessScrollBar(rc, 0, cyNeeded);
}
else{
CControlUI::SetPos(rc);
if( m_items.IsEmpty() ) return;
rc.left += m_rcInset.left;
rc.top += m_rcInset.top;
rc.right -= m_rcInset.right;
rc.bottom -= m_rcInset.bottom;
for( int it = 0; it < m_items.GetSize(); it++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) {
SetFloatPos(it);
}
else {
pControl->SetPos(rc); // 所有非float子控件放大到整个客户区
}
}
}
}
void CContainerUI::SetScrollPos(SIZE szPos)
{
..............
RECT rcPos;
for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);
if( !pControl->IsVisible() ) continue;
if( (!m_pVerticalScrollBar) && (!m_pHorizontalScrollBar))//modify 2014-11-14
{
if( pControl->IsFloat() )
//SetFloatPos(it2);
continue;
}
rcPos = pControl->GetPos();
rcPos.left -= cx;
rcPos.right -= cx;
rcPos.top -= cy;
rcPos.bottom -= cy;
pControl->SetPos(rcPos);
}
Invalidate();
}
滚动条事件响应
void CContainerUI::DoEvent(TEventUI& event)
{
if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {
if( m_pParent != NULL ) m_pParent->DoEvent(event);
else CControlUI::DoEvent(event);
return;
}
if( event.Type == UIEVENT_TIMER && event.wParam == SCROLL_TIMERID )//modify 2014-11-14
{
if( (m_uButtonState1 & UISTATE_CAPTURED) != 0 ) {
POINT pt = m_pManager->GetMousePos();
LONG cy = (pt.y - m_ptLastMouse.y);
m_ptLastMouse = pt;
SIZE sz = GetScrollPos();
sz.cy -= cy;
SetScrollPos(sz);
return;
}
else if( m_dwDelayLeft > 0 ) {
--m_dwDelayLeft;
SIZE sz = GetScrollPos();
LONG lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
if( (lDeltaY > 0 && sz.cy != 0) || (lDeltaY < 0 && sz.cy != GetScrollRange().cy ) ) {
sz.cy -= lDeltaY;
SetScrollPos(sz);
return;
}
}
m_dwDelayDeltaY = 0;
m_dwDelayNum = 0;
m_dwDelayLeft = 0;
m_pManager->KillTimer(this, SCROLL_TIMERID);
return;
}
if( event.Type == UIEVENT_BUTTONDOWN && IsEnabled() )
{
m_uButtonState1 |= UISTATE_CAPTURED;
m_ptLastMouse = event.ptMouse;
m_dwDelayDeltaY = 0;
m_dwDelayNum = 0;
m_dwDelayLeft = 0;
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)));
m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
//return;
}
if( event.Type == UIEVENT_BUTTONUP )
{
if( (m_uButtonState1 & UISTATE_CAPTURED) != 0 ) {
m_uButtonState1 &= ~UISTATE_CAPTURED;
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
if( m_ptLastMouse.y != event.ptMouse.y ) {
m_dwDelayDeltaY = (event.ptMouse.y - m_ptLastMouse.y);
if( m_dwDelayDeltaY > 120 ) m_dwDelayDeltaY = 120;
else if( m_dwDelayDeltaY < -120 ) m_dwDelayDeltaY = -120;
m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
m_dwDelayLeft = m_dwDelayNum;
}
else
m_pManager->KillTimer(this, SCROLL_TIMERID);
}
//return;
}
if( event.Type == UIEVENT_SCROLLWHEEL )
{
LONG lDeltaY = 0;
if( m_dwDelayNum > 0 ) lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
switch( LOWORD(event.wParam) ) {
case SB_LINEUP:
if( m_dwDelayDeltaY >= 0 ) m_dwDelayDeltaY = lDeltaY + 8;
else m_dwDelayDeltaY = lDeltaY + 12;
break;
case SB_LINEDOWN:
if( m_dwDelayDeltaY <= 0 ) m_dwDelayDeltaY = lDeltaY - 8;
else m_dwDelayDeltaY = lDeltaY - 12;
break;
}
if( m_dwDelayDeltaY > 100 ) m_dwDelayDeltaY = 100;
else if( m_dwDelayDeltaY < -100 ) m_dwDelayDeltaY = -100;
m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
m_dwDelayLeft = m_dwDelayNum;
m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
return;
}
直接使用HorLayout或者VerLayout就行了