// PushButton.cpp : Implementation of cPushButton #include "stdafx.h" #include "DecalControls.h" #include "PushButton.h" ///////////////////////////////////////////////////////////////////////////// // cPushButton cPushButton::cPushButton() : m_bPressed( VARIANT_FALSE ), m_bMouseIn( VARIANT_FALSE ), m_nFaceColor( RGB( 140, 80, 30 ) ), m_nTextColor( RGB( 240, 240, 120 ) ), m_UseFaceColor(false) // GKusnick: Render 3D outline. { } void cPushButton::onCreate() { // This control draws over it's entire area m_pSite->put_Transparent( VARIANT_FALSE ); } STDMETHODIMP cPushButton::get_Image(IImageCacheDisp **pVal) { _ASSERTE( pVal != NULL ); if( m_pBackground.p == NULL ) *pVal = NULL; else m_pBackground->QueryInterface( pVal ); return S_OK; } STDMETHODIMP cPushButton::putref_Image(IImageCacheDisp *newVal) { if( m_pBackground.p ) m_pBackground.Release(); if( newVal != NULL ) { HRESULT hRes = newVal->QueryInterface( &m_pBackground ); _ASSERTE( SUCCEEDED( hRes ) ); } m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cPushButton::get_Font(IFontCacheDisp **pVal) { _ASSERTE( pVal != NULL ); if( m_pFont.p == NULL ) *pVal = NULL; else m_pFont->QueryInterface( pVal ); return S_OK; } STDMETHODIMP cPushButton::putref_Font(IFontCacheDisp *newVal) { _ASSERTE( newVal != NULL ); if( m_pFont.p ) m_pFont.Release(); HRESULT hRes = newVal->QueryInterface( &m_pFont ); _ASSERTE( SUCCEEDED( hRes ) ); m_pSite->Reformat(); return S_OK; } STDMETHODIMP cPushButton::get_Text(BSTR *pVal) { _ASSERTE( pVal != NULL ); *pVal = OLE2BSTR( m_strText ); return S_OK; } STDMETHODIMP cPushButton::put_Text(BSTR newVal) { _ASSERTE( newVal != NULL ); m_strText = newVal; m_pSite->Reformat(); m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cPushButton::get_FaceColor(long *pVal) { _ASSERTE( pVal != NULL ); *pVal = m_nFaceColor; return S_OK; } STDMETHODIMP cPushButton::put_FaceColor(long newVal) { _ASSERTE( ( newVal & 0xFF000000L ) == 0 ); m_nFaceColor = newVal; m_UseFaceColor = true; // GKusnick: Render 3D outline. m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cPushButton::get_TextColor(long *pVal) { _ASSERTE( pVal != NULL ); *pVal = m_nTextColor; return S_OK; } STDMETHODIMP cPushButton::put_TextColor(long newVal) { _ASSERTE( ( newVal & 0xFF000000L ) == 0 ); m_nTextColor = newVal; m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cPushButton::SchemaLoad( IView *pView, IUnknown *pSchema ) { CComPtr< IPluginSite > pPlugin; m_pSite->get_PluginSite( &pPlugin ); // Load some defaults pPlugin->CreateFontSchema( 14, 0, pSchema, &m_pFont ); pPlugin->LoadImageSchema( pSchema, &m_pBackground ); MSXML::IXMLDOMElementPtr pElement = pSchema; _variant_t vFaceColor = pElement->getAttribute( _T( "facecolor" ) ), vTextColor = pElement->getAttribute( _T( "textcolor" ) ), vText = pElement->getAttribute( _T( "text" ) ), vAntialias = pElement->getAttribute( _T( "aa" ) ); if( vFaceColor.vt != VT_NULL ) { try { m_nFaceColor = static_cast< long >( vFaceColor ); m_UseFaceColor = true; // GKusnick: Render 3D outline. } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } if( vTextColor.vt != VT_NULL ) { try { m_nTextColor = static_cast< long >( vTextColor ); } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } if( vText.vt != VT_NULL ) { _ASSERTE( vText.vt == VT_BSTR ); m_strText = vText.bstrVal; } m_bAA = true; if( vAntialias.vt != VT_NULL ) { try { m_bAA = static_cast< bool >( vAntialias ); } catch( ... ) { // Type conversion error _ASSERTE( FALSE ); } } return S_OK; } STDMETHODIMP cPushButton::MouseEnter(struct MouseState *) { _ASSERTE( !m_bMouseIn ); m_bMouseIn = VARIANT_TRUE; if( m_bPressed ) { long nID; m_pSite->get_ID( &nID ); Fire_Hit( nID ); _ASSERTE( m_pSite.p != NULL ); m_pSite->Invalidate(); } return S_OK; } STDMETHODIMP cPushButton::MouseExit(struct MouseState *) { _ASSERTE( m_bMouseIn ); m_bMouseIn = VARIANT_FALSE; if( m_bPressed ) { long nID; m_pSite->get_ID( &nID ); Fire_Unhit( nID ); _ASSERTE( m_pSite.p != NULL ); m_pSite->Invalidate(); } return S_OK; } STDMETHODIMP cPushButton::MouseDown(struct MouseState *) { _ASSERTE( m_pSite != NULL ); long nID; m_pSite->get_ID( &nID ); Fire_Hit( nID ); m_bPressed = VARIANT_TRUE; m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cPushButton::MouseUp(struct MouseState *) { m_bPressed = VARIANT_FALSE; long nID; m_pSite->get_ID( &nID ); if( m_bMouseIn ) { _ASSERTE( m_pSite.p != NULL ); m_pSite->Invalidate(); // NOTE: The command may destroy the control synchronously // so we make a stack copy of the target in case our instance is destroyed // for the purpose of completing the command Fire_Accepted( nID ); Fire_Unhit( nID ); } else Fire_Canceled( nID ); return S_OK; } STDMETHODIMP cPushButton::Reformat() { // Everything looks good, calculate the offset of the text if( m_pFont.p == NULL ) { // No font was specified, create the default font CComPtr< IPluginSite > pPlugin; m_pSite->get_PluginSite( &pPlugin ); BSTR bstrFontName; pPlugin->get_FontName(&bstrFontName); pPlugin->CreateFont( bstrFontName /*_bstr_t( _T( "Times New Roman" ) )*/, 14, 0, &m_pFont ); } RECT rc; m_pSite->get_Position( &rc ); SIZE szText; m_pFont->MeasureText( m_strText, &szText ); m_ptText.x = ( ( rc.right - rc.left ) - szText.cx ) / 2; m_ptText.y = ( ( rc.bottom - rc.top ) - szText.cy ) / 2; return S_OK; } STDMETHODIMP cPushButton::Render( ICanvas *pCanvas ) { _ASSERTE( pCanvas != NULL ); _ASSERTE( m_pSite.p != NULL ); RECT rcPos; m_pSite->get_Position( &rcPos ); RECT rcClient = { 0, 0, rcPos.right - rcPos.left, rcPos.bottom - rcPos.top }; bool bPressed = ( m_bPressed && m_bMouseIn ); // First draw the background if( m_pBackground.p == NULL ) pCanvas->Fill( &rcClient, m_nFaceColor ); else { POINT ptOrg = { ( bPressed ) ? 1 : 0, ( bPressed ) ? 1 : 0 }; m_pBackground->PatBlt( pCanvas, &rcClient, &ptOrg ); } // Next, draw the text POINT ptText = { ( !bPressed ) ? m_ptText.x : m_ptText.x + 1, ( !bPressed ) ? m_ptText.y : m_ptText.y + 1 }; m_pFont->DrawTextEx( &ptText, m_strText, m_nTextColor, 0, m_bAA ? eAA : 0, pCanvas ); // Nerfgolem 2001.10.11 // Do not render the 3D outline if there's a background image. // GKusnick: Do render it if there's an explicit face color. if( m_pBackground.p == NULL || m_UseFaceColor ) { // Last, draw the '3D' border - colors are generated relative to the face color // and the design is taken from the windows button long nBrightest = RGB( ( 255 - GetRValue( m_nFaceColor ) ) / 2 + GetRValue( m_nFaceColor ), ( 255 - GetGValue( m_nFaceColor ) ) / 2 + GetGValue( m_nFaceColor ), ( 255 - GetBValue( m_nFaceColor ) ) / 2 + GetBValue( m_nFaceColor ) ), nDarkShadow = RGB( GetRValue( m_nFaceColor ) / 4, GetGValue( m_nFaceColor ) / 4, GetBValue( m_nFaceColor ) / 4 ), nShadow = RGB( GetRValue( m_nFaceColor ) / 2, GetGValue( m_nFaceColor ) / 2, GetBValue( m_nFaceColor ) / 2 ); RECT rcOuterLeft = { 0, 0, 1, rcClient.bottom - 1 }, rcInnerLeft = { 1, 1, 2, rcClient.bottom - 2 }, rcOuterTop = { 0, 0, rcClient.right - 1, 1 }, rcInnerTop = { 1, 1, rcClient.right - 2, 2 }, rcOuterRight = { rcClient.right - 1, 0, rcClient.right, rcClient.bottom }, rcInnerRight = { rcClient.right - 2, 1, rcClient.right - 1, rcClient.bottom - 1 }, rcOuterBottom = { 0, rcClient.bottom - 1, rcClient.right, rcClient.bottom }, rcInnerBottom = { 1, rcClient.bottom - 2, rcClient.right - 1, rcClient.bottom - 1 }; if( bPressed ) { pCanvas->Fill( &rcOuterLeft, nDarkShadow ); pCanvas->Fill( &rcOuterTop, nDarkShadow ); pCanvas->Fill( &rcOuterRight, nBrightest ); pCanvas->Fill( &rcOuterBottom, nBrightest ); pCanvas->Fill( &rcInnerLeft, nShadow ); pCanvas->Fill( &rcInnerTop, nShadow ); pCanvas->Fill( &rcInnerRight, m_nFaceColor ); pCanvas->Fill( &rcInnerBottom, m_nFaceColor ); } else { pCanvas->Fill( &rcOuterLeft, nBrightest ); pCanvas->Fill( &rcOuterTop, nBrightest ); pCanvas->Fill( &rcOuterRight, nDarkShadow ); pCanvas->Fill( &rcOuterBottom, nDarkShadow ); pCanvas->Fill( &rcInnerLeft, m_nFaceColor ); pCanvas->Fill( &rcInnerTop, m_nFaceColor ); pCanvas->Fill( &rcInnerRight, nShadow ); pCanvas->Fill( &rcInnerBottom, nShadow ); } } return S_OK; }