Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
// Filename: ScrollHelper.cpp
// 2005-07-01 nschan Initial revision.
// 2005-09-08 nschan Added GetClientRectSB() function.
#include "stdafx.h"
#include "debug.h"
#include "Scroller.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// ............................................................................
void WinScroller::SetTargetSize(int targetWidth, int targetHeight)
{
scroller_target_size = CSize(targetWidth, targetHeight);
//if (m_attachWnd != NULL && ::IsWindow(m_attachWnd->m_hWnd))
// UpdateScrollInfo();
}
// ............................................................................
BOOL WinScroller::OnMouseWheel(CSize ratio, CPoint ptMouse)
{
if (m_attachWnd == NULL)
return FALSE;
//TODO, should be otional to zoom on current mouse position
::ScreenToClient(m_attachWnd->GetSafeHwnd(), &ptMouse);
CRect rect;
GetClientRectSB(m_attachWnd, rect);
CPoint new_size(::MulDiv(ratio.cy, scroller_target_size.cx, ratio.cx), ::MulDiv(ratio.cy, scroller_target_size.cy, ratio.cx));
std::cout << "new scroll size: " << scroller_target_size << std::endl;
if (bEnabled)
{
scroller_target_size = new_size;
CPoint new_cent(ptMouse + m_scrollPos);
CPoint new_spos(::MulDiv(ratio.cy, new_cent.x, ratio.cx), ::MulDiv(ratio.cy, new_cent.y, ratio.cx));
m_scrollPos = new_spos;
}
else
{
auto x = new_size.x - scroller_target_size.cx;
x = ::MulDiv(x, ptMouse.x, scroller_target_size.cx);
m_scrollPos.cx += x;
auto y = new_size.y - scroller_target_size.cy;
y = ::MulDiv(y, ptMouse.y, scroller_target_size.cy);
m_scrollPos.cy += y;
scroller_target_size = new_size;
}
UpdateScrollInfo();
return TRUE;
}
// ............................................................................
bool WinScroller::UpdateScrollInfo()
{
if (m_attachWnd == NULL)
return false;
// Get the width/height of the attached wnd that includes the area
// covered by the scrollbars (if any). The reason we need this is
// because when scrollbars are present, both cx/cy and GetClientRect()
// when accessed from OnSize() do not include the scrollbar covered
// areas. In other words, their values are smaller than what you would
// expect.
CRect rect;
GetClientRectSB(m_attachWnd, rect);
scroller_screen_size.SetSize(rect.Width(), rect.Height());
std::cout << "UpdateScrollInfo: "
<< " target: " << scroller_target_size
<< " screen: " << scroller_screen_size
<< " pos: " << GetScrollPos() << std::endl;
CSize windowSize(rect.Width(), rect.Height());
if (!bEnabled && bInit)
return false;
CSize deltaPos(0, 0);
UpdateScrollBar(SB_HORZ, windowSize.cx, scroller_target_size.cx, scroller_screen_size.cx, m_scrollPos.cx, deltaPos.cx);
UpdateScrollBar(SB_VERT, windowSize.cy, scroller_target_size.cy, scroller_screen_size.cy, m_scrollPos.cy, deltaPos.cy);
bInit = true;
return false;
}
// ............................................................................
void WinScroller::UpdateScrollBar(int bar, int windowSize, int displaySize,
LONG& pageSize, LONG& scrollPos, LONG& deltaPos)
{
//std::cout << "UpdateScrollBar: " << displaySize << std::endl;
int scrollMax= 0;
deltaPos= 0;
if ( windowSize < displaySize && bEnabled )
{
scrollMax= displaySize - 1;
pageSize= windowSize;
scrollPos= min( scrollPos, displaySize - pageSize - 1 );
deltaPos= m_attachWnd->GetScrollPos( bar ) - scrollPos;
}
else
{
// Force the scrollbar to go away.
pageSize= 0;
scrollPos= 0;
deltaPos= m_attachWnd->GetScrollPos( bar );
}
SCROLLINFO si= { 0 };
si.cbSize= sizeof( SCROLLINFO );
si.fMask= SIF_ALL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS;
si.nMin= 0;
si.nMax= scrollMax;
si.nPage= pageSize;
si.nPos= scrollPos;
m_attachWnd->SetScrollInfo( bar, &si, TRUE );
}
// ............................................................................
int WinScroller::Get32BitScrollPos(int bar, CScrollBar* pScrollBar)
{
// Code below is from MSDN Article ID 152252, "How To Get
// 32-bit Scroll Position During Scroll Messages".
// First determine if the user scrolled a scroll bar control
// on the window or scrolled the window itself.
ASSERT( m_attachWnd != NULL );
HWND hWndScroll;
if ( pScrollBar == NULL )
hWndScroll = m_attachWnd->m_hWnd;
else
hWndScroll = pScrollBar->m_hWnd;
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_TRACKPOS;
::GetScrollInfo(hWndScroll, bar, &si);
int scrollPos = si.nTrackPos;
return scrollPos;
}
// ............................................................................
void WinScroller::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if ( m_attachWnd == NULL )
return;
const int lineOffset = 2;
// Compute the desired change or delta in scroll position.
int deltaPos = 0;
switch( nSBCode )
{
case SB_LINELEFT:
// Left scroll arrow was pressed.
deltaPos = -lineOffset;
break;
case SB_LINERIGHT:
// Right scroll arrow was pressed.
deltaPos = lineOffset;
break;
case SB_PAGELEFT:
// User clicked inbetween left arrow and thumb.
deltaPos = -scroller_screen_size.cx;
break;
case SB_PAGERIGHT:
// User clicked inbetween thumb and right arrow.
deltaPos = scroller_screen_size.cx;
break;
case SB_THUMBTRACK:
// Scrollbar thumb is being dragged.
deltaPos = Get32BitScrollPos(SB_HORZ, pScrollBar) - m_scrollPos.cx;
break;
case SB_THUMBPOSITION:
// Scrollbar thumb was released.
deltaPos = Get32BitScrollPos(SB_HORZ, pScrollBar) - m_scrollPos.cx;
break;
default:
// We don't process other scrollbar messages.
return;
}
// Compute the new scroll position.
int newScrollPos = m_scrollPos.cx + deltaPos;
// If the new scroll position is negative, we adjust
// deltaPos in order to scroll the window back to origin.
if ( newScrollPos < 0 )
deltaPos = -m_scrollPos.cx;
// If the new scroll position is greater than the max scroll position,
// we adjust deltaPos in order to scroll the window precisely to the
// maximum position.
int maxScrollPos = scroller_target_size.cx - scroller_screen_size.cx;
if ( newScrollPos > maxScrollPos )
deltaPos = maxScrollPos - m_scrollPos.cx;
// Scroll the window if needed.
if ( deltaPos != 0 )
{
m_scrollPos.cx += deltaPos;
m_attachWnd->SetScrollPos(SB_HORZ, m_scrollPos.cx, TRUE);
m_attachWnd->ScrollWindow(-deltaPos, 0);
}
}
// ............................................................................
void WinScroller::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if ( m_attachWnd == NULL )
return;
const int lineOffset = 60;
// Compute the desired change or delta in scroll position.
int deltaPos = 0;
switch( nSBCode )
{
case SB_LINEUP:
// Up arrow button on scrollbar was pressed.
deltaPos = -lineOffset;
break;
case SB_LINEDOWN:
// Down arrow button on scrollbar was pressed.
deltaPos = lineOffset;
break;
case SB_PAGEUP:
// User clicked inbetween up arrow and thumb.
deltaPos = -scroller_screen_size.cy;
break;
case SB_PAGEDOWN:
// User clicked inbetween thumb and down arrow.
deltaPos = scroller_screen_size.cy;
break;
case SB_THUMBTRACK:
// Scrollbar thumb is being dragged.
deltaPos = Get32BitScrollPos(SB_VERT, pScrollBar) - m_scrollPos.cy;
break;
case SB_THUMBPOSITION:
// Scrollbar thumb was released.
deltaPos = Get32BitScrollPos(SB_VERT, pScrollBar) - m_scrollPos.cy;
break;
default:
// We don't process other scrollbar messages.
return;
}
// Compute the new scroll position.
int newScrollPos = m_scrollPos.cy + deltaPos;
// If the new scroll position is negative, we adjust
// deltaPos in order to scroll the window back to origin.
if ( newScrollPos < 0 )
deltaPos = -m_scrollPos.cy;
// If the new scroll position is greater than the max scroll position,
// we adjust deltaPos in order to scroll the window precisely to the
// maximum position.
int maxScrollPos = scroller_target_size.cy - scroller_screen_size.cy;
if ( newScrollPos > maxScrollPos )
deltaPos = maxScrollPos - m_scrollPos.cy;
// Scroll the window if needed.
if ( deltaPos != 0 )
{
m_scrollPos.cy += deltaPos;
m_attachWnd->SetScrollPos(SB_VERT, m_scrollPos.cy, TRUE);
m_attachWnd->ScrollWindow(0, -deltaPos);
}
}
// ............................................................................
// Helper function to get client rect with possible
// modification by adding scrollbar width/height.
void GetClientRectSB( CWnd* pWnd, CRect& rect )
{
ASSERT( pWnd != NULL );
CRect winRect;
pWnd->GetWindowRect( &winRect );
pWnd->ScreenToClient( &winRect );
pWnd->GetClientRect( &rect );
int cxSB = ::GetSystemMetrics( SM_CXVSCROLL );
int cySB = ::GetSystemMetrics( SM_CYHSCROLL );
if( winRect.right >= rect.right + cxSB )
rect.right+= cxSB;
if( winRect.bottom >= rect.bottom + cySB )
rect.bottom+= cySB;
}
// ............................................................................
void WinScroller::ScrollToOrigin( bool scrollLeft, bool scrollTop )
{
if ( m_attachWnd == NULL )
return;
if ( scrollLeft )
{
if ( scroller_target_size.cx > 0 && scroller_screen_size.cx > 0 && m_scrollPos.cx > 0 )
{
int deltaPos = -m_scrollPos.cx;
m_scrollPos.cx += deltaPos;
m_attachWnd->SetScrollPos(SB_HORZ, m_scrollPos.cx, TRUE);
m_attachWnd->ScrollWindow(-deltaPos, 0);
}
}
if ( scrollTop )
{
if ( scroller_target_size.cy > 0 && scroller_screen_size.cy > 0 && m_scrollPos.cy > 0 )
{
int deltaPos = -m_scrollPos.cy;
m_scrollPos.cy += deltaPos;
m_attachWnd->SetScrollPos(SB_VERT, m_scrollPos.cy, TRUE);
m_attachWnd->ScrollWindow(0, -deltaPos);
}
}
}
// END
9089253afThis file is pinned to the selected release. Download the original to open it in your design tool.