• 10
• 9
• 10
• 9
• 10

# Win32 scrollbars

This topic is 2233 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have a dialog window which I create from a resource. It has a couple of scrollbar controls on it (not the default vertical/horizontal scrollbars on a window, these have been manually placed)

I set their max range and position when I create the dialog, and they display fine, with the thumb at 'zero' and of an appropriate size for the range and page size I specify. The problem I'm having is that when I drag the thumb into a new position, as soon as I let go they 'pop' back to their original place. From reading the documentation, I was under the impression that they automatically update the thumb's position variable when they are dragged, so I just need to call GetScrollInfo and extract the thumb position. The position of mine is always zero however.

Is there a 'just been dragged' message I need to capture to update the scrollbar's position variable myself?

##### Share on other sites
Unfortunately using a scrollbar directly in Win32 is lots of extra work. Basically you need to handle all WM_HSCROLL/WM_VSCROLL cases and call SetScrollPos to adjust the scrollbar pos yourself.

A sample code, will probably not compile as is. Please ignore the ugly var naming. This code was using MFC, but the same functions are available in pure Win32 with another parameter for the HWND.

 void CCheckListBox::OnVScroll( UINT nSBCode, UINT nPos, HWND hwndScrollBar ) { int iMin, iMax; GetScrollRange( SB_VERT, &iMin, &iMax ); if ( iMax == 0 ) { return; } RECT rc; GetClientRect( &rc ); int iVisibleItems = rc.bottom / m_iItemHeight * m_iItemsPerLine, iPageItems = ( iVisibleItems * 3 / 4 ) - ( iVisibleItems * 3 / 4 ) % m_iItemsPerLine; bool bChanged = false; switch ( nSBCode ) { case SB_LEFT: if ( m_iOffset > 0 ) { m_iOffset = 0; bChanged = true; } break; case SB_LINELEFT: if ( m_iOffset > 0 ) { m_iOffset -= m_iItemsPerLine; if ( m_iOffset < 0 ) { m_iOffset = 0; } bChanged = true; } break; case SB_PAGELEFT: if ( m_iOffset > 0 ) { if ( iPageItems > (int)m_iOffset ) { m_iOffset = 0; } else { m_iOffset -= iPageItems; } bChanged = true; } break; case SB_LINERIGHT: { size_t iNewOffset = m_iOffset; iNewOffset += m_iItemsPerLine; if ( iNewOffset >= m_vectItems.size() - iVisibleItems ) { iNewOffset = m_vectItems.size() - iVisibleItems; iNewOffset -= iNewOffset % m_iItemsPerLine; } if ( iNewOffset != m_iOffset ) { m_iOffset = iNewOffset; bChanged = true; } } break; case SB_PAGERIGHT: { size_t iNewOffset = m_iOffset; iNewOffset += iPageItems; if ( iNewOffset >= m_vectItems.size() - iVisibleItems ) { iNewOffset = m_vectItems.size() - iVisibleItems; iNewOffset -= iNewOffset % m_iItemsPerLine; } if ( iNewOffset != m_iOffset ) { m_iOffset = iNewOffset; bChanged = true; } } break; case SB_RIGHT: { size_t iNewOffset = m_iOffset; iNewOffset += iPageItems; iNewOffset = m_vectItems.size() - iVisibleItems; iNewOffset -= iNewOffset % m_iItemsPerLine; if ( iNewOffset != m_iOffset ) { m_iOffset = iNewOffset; bChanged = true; } } break; case SB_THUMBPOSITION: case SB_THUMBTRACK: { size_t iNewOffset = m_iOffset; iNewOffset = nPos; iNewOffset -= iNewOffset % m_iItemsPerLine; if ( iNewOffset < 0 ) { iNewOffset = 0; } if ( iNewOffset != m_iOffset ) { m_iOffset = iNewOffset; bChanged = true; } } break; case SB_ENDSCROLL: //End scroll. default: break; } if ( bChanged ) { Invalidate(); } SetScrollPos( SB_VERT, (int)m_iOffset, TRUE ); } 

##### Share on other sites
Ah, brilliant thanks.

I'd looked at WM_HSCROLL and WM_VSCROLL, but I'd thought they were called when the default window scrollbars were used, I didn't realise they applied to manually-placed scrollbars too.

I've got it working now, thanks