// Scroller.cpp : Implementation of cScroller #include "stdafx.h" #include "DecalControls.h" #include "Scroller.h" enum eScrollChildren { eScrollerUp = 1, eScrollerDown = 2, eScrollerRight = 3, eScrollerLeft = 4, eScrollerPager = 5, eScrollerPageUp = 6, eScrollerPageDown = 7, eScrollerPageLeft = 8, eScrollerPageRight = 9, eScrollerClient = 10, eScrollerHThumb = 11, eScrollerVThumb = 12 }; ///////////////////////////////////////////////////////////////////////////// // cScroller void cScroller::onCreate() { // Initialize our layout options m_szArea.cx = 0; m_szArea.cy = 0; m_szIncrement.cx = 100; m_szIncrement.cy = 20; m_ptThumb.x = 0; m_ptThumb.y = 0; m_bHScroll = VARIANT_FALSE; m_bVScroll = VARIANT_FALSE; CComPtr< ILayer > pLayerPager; HRESULT hRes = ::CoCreateInstance( __uuidof( Pager ), NULL, CLSCTX_INPROC_SERVER, __uuidof( ILayer ), reinterpret_cast< void ** >( &pLayerPager ) ); _ASSERTE( SUCCEEDED( hRes ) ); LayerParams p = { eScrollerPager, { 0, 0, 0, 0 }, eRenderClipped }; m_pSite->CreateChild( &p, pLayerPager ); pLayerPager->QueryInterface( &m_pPager ); IPagerEventsImpl< PAGER_CLIENT, cScroller >::advise( m_pPager ); CComPtr< ILayer > pLayerUp; hRes = ::CoCreateInstance( __uuidof( Button ), NULL, CLSCTX_INPROC_SERVER, __uuidof( ILayer ), reinterpret_cast< void ** >( &pLayerUp ) ); _ASSERTE( SUCCEEDED( hRes ) ); p.ID = eScrollerUp; CComPtr< IButton > pUp; m_pSite->CreateChild( &p, pLayerUp ); pLayerUp->QueryInterface( &pUp); ICommandEventsImpl< BUTTON_UP, cScroller >::advise( pUp ); pUp->SetImages( 0, 0x06001261, 0x06001262 ); pUp->put_Matte( RGB( 0, 0, 0 ) ); CComPtr< ILayer > pLayerDown; hRes = ::CoCreateInstance( __uuidof( Button ), NULL, CLSCTX_INPROC_SERVER, __uuidof( ILayer ), reinterpret_cast< void ** >( &pLayerDown ) ); _ASSERTE( SUCCEEDED( hRes ) ); p.ID = eScrollerDown; CComPtr< IButton > pDown; m_pSite->CreateChild( &p, pLayerDown ); pLayerDown->QueryInterface( &pDown ); ICommandEventsImpl< BUTTON_DOWN, cScroller >::advise( pDown ); pDown->SetImages( 0, 0x0600125E, 0x0600125F ); pDown->put_Matte( RGB( 0, 0, 0 ) ); CComPtr< ILayer > pLayerLeft; hRes = ::CoCreateInstance( __uuidof( Button ), NULL, CLSCTX_INPROC_SERVER, __uuidof( ILayer ), reinterpret_cast< void ** >( &pLayerLeft ) ); _ASSERTE( SUCCEEDED( hRes ) ); p.ID = eScrollerLeft; CComPtr< IButton > pLeft; m_pSite->CreateChild( &p, pLayerLeft ); pLayerLeft->QueryInterface( &pLeft ); ICommandEventsImpl< BUTTON_LEFT, cScroller >::advise( pLeft ); pLeft->SetImages( 0, 0x06001295, 0x06001296 ); pLeft->put_Matte( RGB( 0, 0, 0 ) ); CComPtr< ILayer > pLayerRight; hRes = ::CoCreateInstance( __uuidof( Button ), NULL, CLSCTX_INPROC_SERVER, __uuidof( ILayer ), reinterpret_cast< void ** >( &pLayerRight ) ); _ASSERTE( SUCCEEDED( hRes ) ); p.ID = eScrollerRight; CComPtr< IButton > pRight; m_pSite->CreateChild( &p, pLayerRight ); pLayerRight->QueryInterface( &pRight ); ICommandEventsImpl< BUTTON_RIGHT, cScroller >::advise( pRight ); pRight->SetImages( 0, 0x06001298, 0x06001299 ); pRight->put_Matte( RGB( 0, 0, 0 ) ); // Positioning will occur during Reformat // Load the images CComPtr< IPluginSite > pPlugin; m_pSite->get_PluginSite( &pPlugin ); pPlugin->LoadBitmapPortal( 0x06001260, &m_pVScrollBack ); pPlugin->LoadBitmapPortal( 0x06001297, &m_pHScrollBack ); } void cScroller::onDestroy() { m_pPager.Release(); } void cScroller::constrainOffset( LPPOINT ppt ) { // First check for overflow, furthest scroll should be allowed is less a // page size POINT ptMax = { m_szArea.cx, m_szArea.cy }; SIZE szViewport; get_Viewport( &szViewport ); if((szViewport.cx % m_szIncrement.cx)==0) ptMax.x -= szViewport.cx; else ptMax.x -= ( szViewport.cx / m_szIncrement.cx + 1) * m_szIncrement.cx; if((szViewport.cy % m_szIncrement.cy)==0) ptMax.y -= szViewport.cy; else ptMax.y -= ( szViewport.cy / m_szIncrement.cy + 1) * m_szIncrement.cy; // substract the viewport (rounded up a notch) from the max scroll area // ptMax.x -= ( szViewport.cx / m_szIncrement.cx + 1) * m_szIncrement.cx; // ptMax.y -= ( szViewport.cy / m_szIncrement.cy + 1) * m_szIncrement.cy; if( ppt->x > ptMax.x ) ppt->x = ptMax.x; if( ppt->y > ptMax.y ) ppt->y = ptMax.y; // Check for underflow (either because it was assigned too low // or or max is too low) if( ppt->x < 0 ) ppt->x = 0; if( ppt->y < 0 ) ppt->y = 0; } #define BTN_SIZE 16 long cScroller::hitTest( MouseState *pMS ) { if( pMS->over != this ) return -1; SIZE szViewport; get_Viewport( &szViewport ); RECT rcScroll = { BTN_SIZE, BTN_SIZE, szViewport.cx - BTN_SIZE, szViewport.cy - BTN_SIZE }; // Check if it's on the horizontal bar if( m_bHScroll ) { if( pMS->client.x > rcScroll.left && pMS->client.x < rcScroll.right && pMS->client.y > szViewport.cy ) { if( m_szArea.cx == szViewport.cx ) // Special case, no scrolling if the area is the minimum size return -1; // We hit the horizontal bar if( pMS->client.x < ( m_ptThumb.x + BTN_SIZE ) ) // Hit before the thumb return eScrollerPageLeft; else if( pMS->client.x > ( m_ptThumb.x + BTN_SIZE * 2 ) ) // Hit after the thumb return eScrollerPageRight; // Hit the thumb return eScrollerHThumb; } } // Check if it's on the vertical bar if( m_bVScroll ) { if( pMS->client.y > rcScroll.top && pMS->client.y < rcScroll.bottom && pMS->client.x > szViewport.cx ) { if( m_szArea.cy == szViewport.cy ) // Special case, no scrolling if the area is the minimum size return -1; // We hit the vertical bar if( pMS->client.y < ( m_ptThumb.y + BTN_SIZE ) ) // Hit above the thumb return eScrollerPageUp; else if( pMS->client.y > ( m_ptThumb.y + BTN_SIZE * 2 ) ) // Hit below thumb return eScrollerPageDown; // Hit the v thumb return eScrollerVThumb; } } return -1; } STDMETHODIMP cScroller::Render(ICanvas *pCanvas) { SIZE szViewport; get_Viewport( &szViewport ); // Fill in the scrollbars as neccessary static POINT ptOff = { 0, 0 }; CComPtr< IPluginSite > pPluginSite; m_pSite->get_PluginSite( &pPluginSite ); SIZE szIcon = { BTN_SIZE, BTN_SIZE }; CComPtr< IIconCache > pIconCache; pPluginSite->GetIconCache( &szIcon, &pIconCache ); if( m_bHScroll ) { RECT rcHScroll = { BTN_SIZE, szViewport.cy, szViewport.cx - BTN_SIZE, szViewport.cy + BTN_SIZE }; m_pHScrollBack->PatBlt( pCanvas, &rcHScroll, &ptOff ); if( m_szArea.cx != szViewport.cx ) { // Draw the H thumb POINT ptHThumb = { BTN_SIZE + m_ptThumb.x, szViewport.cy }; RECT rcThumb = { ptHThumb.x, ptHThumb.y, ptHThumb.x + BTN_SIZE, ptHThumb.y + BTN_SIZE }; pCanvas->Fill( &rcThumb, RGB( 0, 0, 0 ) ); pIconCache->DrawIcon( &ptHThumb, ( m_nCurrentCommand == eScrollerHThumb ) ? 0x06001264 : 0x06001263, 0, pCanvas ); } } if( m_bVScroll ) { RECT rcVScroll = { szViewport.cx, BTN_SIZE, szViewport.cx + BTN_SIZE, szViewport.cy - BTN_SIZE }; m_pVScrollBack->PatBlt( pCanvas, &rcVScroll, &ptOff ); if( m_szArea.cy != szViewport.cy ) { // Draw the V thumb POINT ptVThumb = { szViewport.cx, BTN_SIZE + m_ptThumb.y }; RECT rcThumb = { ptVThumb.x, ptVThumb.y, ptVThumb.x + BTN_SIZE, ptVThumb.y + BTN_SIZE }; pCanvas->Fill( &rcThumb, RGB( 0, 0, 0 ) ); pIconCache->DrawIcon( &ptVThumb, ( m_nCurrentCommand == eScrollerVThumb ) ? 0x06001264 : 0x06001263, 0, pCanvas ); } } if( m_bHScroll && m_bVScroll ) { // Draw the little corner piece RECT rcCorner = { szViewport.cx, szViewport.cy, szViewport.cx + BTN_SIZE, szViewport.cy + BTN_SIZE }; pCanvas->Fill( &rcCorner, RGB( 130, 100, 80 ) ); } return S_OK; } STDMETHODIMP cScroller::Reformat() { SIZE szViewport; get_Viewport( &szViewport ); CComPtr< ILayerSite > pPagerSite; HRESULT hRes = m_pSite->get_Child( eScrollerPager, ePositionByID, &pPagerSite ); RECT rcPager = { 0, 0, szViewport.cx, szViewport.cy }; pPagerSite->put_Position( &rcPager ); CComPtr< ILayerSite > pClientSite; pPagerSite->get_Child( eScrollerClient, ePositionByID, &pClientSite ); RECT rcClient = { 0, 0, m_szArea.cx, m_szArea.cy }; pClientSite->put_Position( &rcClient ); CComPtr< ILayerSite > pUp, pDown, pLeft, pRight; m_pSite->get_Child( eScrollerUp, ePositionByID, &pUp ); m_pSite->get_Child( eScrollerDown, ePositionByID, &pDown ); m_pSite->get_Child( eScrollerLeft, ePositionByID, &pLeft ); m_pSite->get_Child( eScrollerRight, ePositionByID, &pRight ); static RECT rcHidden = { 0, 0, 0, 0 }; if( m_bHScroll ) { RECT rcLeft = { 0, szViewport.cy, BTN_SIZE, szViewport.cy + BTN_SIZE }, rcRight = { szViewport.cx - BTN_SIZE, szViewport.cy, szViewport.cx, szViewport.cy + BTN_SIZE }; pLeft->put_Position( &rcLeft ); pRight->put_Position( &rcRight ); } else { pLeft->put_Position( &rcHidden ); pRight->put_Position( &rcHidden ); } if( m_bVScroll ) { RECT rcUp = { szViewport.cx, 0, szViewport.cx + BTN_SIZE, BTN_SIZE }, rcDown = { szViewport.cx, szViewport.cy - BTN_SIZE, szViewport.cx + BTN_SIZE, szViewport.cy }; pUp->put_Position( &rcUp ); pDown->put_Position( &rcDown ); } else { pUp->put_Position( &rcHidden ); pDown->put_Position( &rcHidden ); } // Calculate the size of the page increments m_szPage.cx = ( szViewport.cx / m_szIncrement.cx ) * m_szIncrement.cx; m_szPage.cy = ( szViewport.cy / m_szIncrement.cy ) * m_szIncrement.cy; return S_OK; } void cScroller::onButtonHit(long nID) { m_pPager->put_Command( nID ); } void cScroller::onButtonUnhit(long) { m_pPager->FinishCommand(); } VARIANT_BOOL cScroller::onClientGetNextPosition(long nID, long nCommand, long *pnX, long *pnY) { POINT ptDest; m_pPager->get_Offset( &ptDest ); POINT ptOriginal = ptDest; switch( nCommand ) { case eScrollerUp: ptDest.y -= m_szIncrement.cy; break; case eScrollerDown: ptDest.y += m_szIncrement.cy; break; case eScrollerPageUp: ptDest.y -= m_szPage.cy; break; case eScrollerPageDown: ptDest.y += m_szPage.cy; break; case eScrollerLeft: ptDest.x -= m_szIncrement.cx; break; case eScrollerRight: ptDest.x += m_szIncrement.cx; break; case eScrollerPageLeft: ptDest.x -= m_szPage.cx; break; case eScrollerPageRight: ptDest.x += m_szPage.cx; break; default: // Unknown scrolling command _ASSERTE( FALSE ); } constrainOffset( &ptDest ); if( ptDest.x == ptOriginal.x && ptDest.y == ptOriginal.y ) // We didn't move this cycle - do not continue return VARIANT_FALSE; *pnX = ptDest.x; *pnY = ptDest.y; return VARIANT_TRUE; } void cScroller::onClientChange( long nID, long, long nX, long nY ) { _ASSERTE( nID == eScrollerPager ); // Convert these values to a thumb-like position SIZE szViewport; get_Viewport( &szViewport ); SIZE szScroll = szViewport; szScroll.cx -= BTN_SIZE * 3; szScroll.cy -= BTN_SIZE * 3; // The viewport is now the size of the thumb ranges m_ptThumb.x = static_cast< long >( ( ( m_szArea.cx - szViewport.cx ) != 0 ) ? static_cast< double >( nX * szScroll.cx ) / static_cast< double >( m_szArea.cx - szViewport.cx ) : 0.0 ); m_ptThumb.y = static_cast< long >( ( ( m_szArea.cy - szViewport.cy ) != 0 ) ? static_cast< double >( nY * szScroll.cy ) / static_cast< double >( m_szArea.cy - szViewport.cy ) : 0.0 ); if( m_ptThumb.x > szScroll.cx || nX >= ( m_szArea.cx - szViewport.cx - m_szIncrement.cy ) ) m_ptThumb.x = szScroll.cx; if( m_ptThumb.y > szScroll.cy || nY >= ( m_szArea.cy - szViewport.cy - m_szIncrement.cy ) ) m_ptThumb.y = szScroll.cy; if( m_ptThumb.x < 0 ) m_ptThumb.x = 0; if( m_ptThumb.y < 0 ) m_ptThumb.y = 0; // Check if the thumb moving has canceled a mouse action switch( m_nCurrentCommand ) { case eScrollerPageUp: case eScrollerPageDown: case eScrollerPageLeft: case eScrollerPageRight: { MouseState ms = { this, { 0, 0 }, { m_ptMouseLast.x, m_ptMouseLast.y }, VARIANT_FALSE, VARIANT_FALSE }; if( hitTest( &ms ) != m_nCurrentCommand ) m_pPager->FinishCommand(); } break; } // Draw next frame m_pSite->Invalidate(); long nIDThis; m_pSite->get_ID( &nIDThis ); Fire_Change( nIDThis, nX, nY ); } STDMETHODIMP cScroller::get_Viewport(LPSIZE pVal) { _ASSERTE( pVal != NULL ); RECT rc; m_pSite->get_Position( &rc ); pVal->cx = ( rc.right - rc.left ) - ( ( m_bVScroll ) ? BTN_SIZE : 0 ); pVal->cy = ( rc.bottom - rc.top ) - ( ( m_bHScroll ) ? BTN_SIZE : 0 ); return S_OK; } STDMETHODIMP cScroller::get_Area(LPSIZE pVal) { _ASSERTE( pVal != NULL ); *pVal = m_szArea; return S_OK; } STDMETHODIMP cScroller::put_Area(LPSIZE newVal) { _ASSERTE( newVal != NULL ); //_ASSERTE( newVal->cx >= 0 && newVal->cy >= 0 ); // Now this area will have to be rounded up to an increment or // a page size SIZE szViewport; get_Viewport( &szViewport ); if( newVal->cx < szViewport.cx ) // This view is thinner than the viewport, set it to the minimum newVal->cx = szViewport.cx; else if( m_bHScroll ) if((szViewport.cx % m_szIncrement.cx)!=0) newVal->cx += m_szIncrement.cx - ( newVal->cx % m_szIncrement.cx ); // Make sure there is an extra line so we don't scroll off the edge // Repeat for y-scoord if( newVal->cy < szViewport.cy ) newVal->cy = szViewport.cy; else if( m_bVScroll ) if((szViewport.cy % m_szIncrement.cy)!=0) newVal->cy += m_szIncrement.cy - ( newVal->cy % m_szIncrement.cy ); m_szArea = *newVal; m_pSite->Reformat(); return S_OK; } STDMETHODIMP cScroller::get_HorizontalEnabled(VARIANT_BOOL *pVal) { _ASSERTE( pVal != NULL ); *pVal = m_bHScroll; return S_OK; } STDMETHODIMP cScroller::put_HorizontalEnabled(VARIANT_BOOL newVal) { if( newVal != m_bHScroll ) { m_bHScroll = newVal; m_pSite->Reformat(); } return S_OK; } STDMETHODIMP cScroller::get_VerticalEnabled(VARIANT_BOOL *pVal) { _ASSERTE( pVal != NULL ); *pVal = m_bVScroll; return S_OK; } STDMETHODIMP cScroller::put_VerticalEnabled(VARIANT_BOOL newVal) { if( newVal != m_bVScroll ) { m_bVScroll = newVal; m_pSite->Reformat(); } return S_OK; } STDMETHODIMP cScroller::CreateClient(ILayer *pChild) { CComPtr< ILayerSite > pPagerSite; HRESULT hRes = m_pSite->get_Child( eScrollerPager, ePositionByID, &pPagerSite ); _ASSERTE( SUCCEEDED( hRes ) ); LayerParams lp = { eScrollerClient, { 0, 0, 0, 0 }, eRenderClipped }; return pPagerSite->CreateChild( &lp, pChild ); } STDMETHODIMP cScroller::get_Offset(LPPOINT pVal) { _ASSERTE( pVal != NULL ); POINT ptTrueOff; m_pPager->get_Offset( &ptTrueOff ); pVal->x = ptTrueOff.x / m_szIncrement.cx; pVal->y = ptTrueOff.y / m_szIncrement.cy; return S_OK; } STDMETHODIMP cScroller::put_Offset(LPPOINT newVal) { _ASSERTE( newVal != NULL ); _ASSERTE( newVal->x >= 0 && newVal->y >= 0 ); POINT ptTrueOff = { newVal->x * m_szIncrement.cx, newVal->y * m_szIncrement.cy }; constrainOffset( &ptTrueOff ); m_pPager->put_Offset( &ptTrueOff ); return S_OK; } STDMETHODIMP cScroller::ScrollTo(LPPOINT ptOffset) { _ASSERTE( ptOffset != NULL ); _ASSERTE( ptOffset->x >= 0 && ptOffset->y >= 0 ); POINT ptTrueOff = { ptOffset->x * m_szIncrement.cx, ptOffset->y * m_szIncrement.cy }; constrainOffset( &ptTrueOff ); m_pPager->ScrollTo( &ptTrueOff ); return S_OK; } STDMETHODIMP cScroller::get_Increments(LPSIZE pVal) { _ASSERTE( pVal != NULL ); *pVal = m_szIncrement; return S_OK; } STDMETHODIMP cScroller::put_Increments(LPSIZE newVal) { _ASSERTE( newVal != NULL ); _ASSERTE( newVal->cx > 0 && newVal->cy > 0 ); // Assign the new increments m_szIncrement = *newVal; // Align the current position to the new position POINT ptCurrent; m_pPager->get_Offset( &ptCurrent ); ptCurrent.x = ( ptCurrent.x / newVal->cx ) * newVal->cx; ptCurrent.y = ( ptCurrent.y / newVal->cy ) * newVal->cy; constrainOffset( &ptCurrent ); m_pPager->put_Offset( &ptCurrent ); m_pSite->Reformat(); return S_OK; } STDMETHODIMP cScroller::MouseDown( MouseState *pMS ) { m_nCurrentCommand = hitTest( pMS ); if( m_nCurrentCommand == -1 ) return S_OK; switch( m_nCurrentCommand ) { case eScrollerHThumb: m_nScreenStart = pMS->screen.x; m_nThumbStart = m_ptThumb.x; break; case eScrollerVThumb: m_nScreenStart = pMS->screen.y; m_nThumbStart = m_ptThumb.y; break; case eScrollerPageUp: case eScrollerPageDown: case eScrollerPageLeft: case eScrollerPageRight: m_ptMouseLast = pMS->client; m_pPager->put_Command( m_nCurrentCommand ); break; } m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cScroller::MouseUp( MouseState *pMS ) { m_nCurrentCommand = -1; // Make sure there are no more commands in the pager m_pPager->FinishCommand(); m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cScroller::MouseMove( MouseState *pMS ) { if( m_nCurrentCommand == -1 ) // No command, so nothgin to do return S_OK; SIZE szViewport; get_Viewport( &szViewport ); SIZE szScroller = { szViewport.cx - BTN_SIZE * 3, szViewport.cy - BTN_SIZE * 3 }; POINT ptOffset; m_pPager->get_Offset( &ptOffset ); switch( m_nCurrentCommand ) { case eScrollerPageUp: case eScrollerPageDown: case eScrollerPageLeft: case eScrollerPageRight: { if( hitTest( pMS ) == m_nCurrentCommand ) m_pPager->put_Command( m_nCurrentCommand ); else m_pPager->FinishCommand(); m_ptMouseLast = pMS->client; } break; case eScrollerHThumb: { long nPos = m_nThumbStart + ( pMS->screen.x - m_nScreenStart ); // Make sure it's bigger than 0 if( nPos < 0 ) nPos = 0; // Convert this to an actual position ptOffset.x = nPos * ( m_szArea.cx - szViewport.cx ) / szScroller.cx; // Align to the nearest line ptOffset.x -= ptOffset.x % m_szIncrement.cx; // Set the position, pager callback will set the thumb position constrainOffset( &ptOffset ); m_pPager->put_Offset( &ptOffset ); } break; case eScrollerVThumb: { long nPos = m_nThumbStart + ( pMS->screen.y - m_nScreenStart ); // Make sure it's bigger than 0 if( nPos < 0 ) nPos = 0; // Convert this to an actual position ptOffset.y = nPos * ( m_szArea.cy - szViewport.cy ) / szScroller.cy; // Align to the nearest line ptOffset.y -= ptOffset.y % m_szIncrement.cy; // Set the position, pager callback will set the thumb position constrainOffset( &ptOffset ); m_pPager->put_Offset( &ptOffset ); } break; } return S_OK; } HRESULT cScroller::SchemaLoad( IView *pView, IUnknown *pXMLElement ) { MSXML::IXMLDOMElementPtr pElement = pXMLElement; _variant_t vHScroll = pElement->getAttribute( _T( "hscroll" ) ), vVScroll = pElement->getAttribute( _T( "vscroll" ) ), vAreaWidth = pElement->getAttribute( _T( "areawidth" ) ), vAreaHeight = pElement->getAttribute( _T( "areaheight" ) ), vIncrementX = pElement->getAttribute( _T( "incrementx" ) ), vIncrementY = pElement->getAttribute( _T( "incrementy" ) ); // Do the client MSXML::IXMLDOMElementPtr pClient = pElement->selectSingleNode( _T( "control" ) ); if( pClient.GetInterfacePtr() != NULL ) { // Recurse and load the client CComPtr< ILayerSite > pPager; m_pSite->get_Child( eScrollerPager, ePositionByID, &pPager ); long nAssigned; pView->LoadControl( pPager, eScrollerClient, pClient, &nAssigned ); } // First enable the scroll bars if( vHScroll.vt != VT_NULL ) { try { m_bHScroll = static_cast< bool >( vHScroll ) ? VARIANT_TRUE : VARIANT_FALSE; } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } if( vVScroll.vt != VT_NULL ) { try { m_bVScroll = static_cast< bool >( vVScroll ) ? VARIANT_TRUE : VARIANT_FALSE; } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } // Next set the increment sizes if( vIncrementX.vt != VT_NULL ) { try { m_szIncrement.cx = static_cast< long >( vIncrementX ); } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } if( vIncrementY.vt != VT_NULL ) { try { m_szIncrement.cy = static_cast< long >( vIncrementY ); } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } // Last, set the area SIZE szArea = m_szArea; if( vAreaWidth.vt != VT_NULL ) { try { szArea.cx = static_cast< long >( vAreaWidth ); } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } if( vAreaHeight.vt != VT_NULL ) { try { szArea.cy = static_cast< long >( vAreaHeight ); } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } put_Area( &szArea ); return S_OK; } STDMETHODIMP cScroller::ResetScroller() { POINT ptCurrent; ptCurrent.x = 0; ptCurrent.y = 0; constrainOffset( &ptCurrent ); m_pPager->put_Offset( &ptCurrent ); m_ptThumb.x =0; m_ptThumb.y =0; return S_OK; }