// View.cpp : Implementation of cView #include "stdafx.h" #include #include "Inject.h" #include "View.h" #include "RootLayer.h" #include "Manager.h" #include "InjectApi.h" ///////////////////////////////////////////////////////////////////////////// // cView cView::~cView( ) { m_bActivated = false; m_pRoot->m_pBars->RemoveBar( m_nViewID ); m_pPanel->RemoveView( m_nViewID ); m_pRoot->removeView( this ); long nActiveView; m_pPanel->get_ActiveView( &nActiveView ); m_pRoot->SelectBar( nActiveView ); m_pRoot->SelectBar( nActiveView ); m_pPanel.Release(); if( cManager::_p->m_bContainer ) cManager::_p->clearDestroyList( ); } long cView::loadSchema( BSTR strSchema, IUnknown **ppRootControl ) { USES_CONVERSION; _ASSERTE( strSchema != NULL ); // Create a new XML document and load this up MSXML::IXMLDOMDocumentPtr pDoc; pDoc.CreateInstance( __uuidof( MSXML::DOMDocument ), NULL, CLSCTX_INPROC_SERVER ); VARIANT_BOOL bSuccess; if( strSchema[ 0 ] == OLESTR( '<' ) ) bSuccess = pDoc->loadXML( strSchema ); else { // Load from a file source pDoc->async = VARIANT_FALSE; TCHAR szPath[ MAX_PATH ]; bSuccess = pDoc->load( ::InjectMapPath( eInjectPathAgent, OLE2T( strSchema ), szPath ) ); } if( !bSuccess ) { USES_CONVERSION; // The document failed to load, get the error info for posterity MSXML::IXMLDOMParseErrorPtr pErr = pDoc->parseError; long nCode = pErr->errorCode; long nFilePos = pErr->filepos; long nLine = pErr->line; long nLinePos = pErr->linepos; _bstr_t strReason = pErr->reason; _bstr_t strText = pErr->srcText; TCHAR szError[ 1024 ]; ::_stprintf( szError, _T( "0x%08X (%i, %i): %s" ), nCode, nLine, nLinePos, OLE2T( strReason ) ); ::MessageBox( cManager::_p->m_hMain, szError, _T( "XML Parse Error" ), MB_ICONERROR | MB_OK ); // Give the user a chance to break and look at this lovely info _ASSERTE( FALSE ); pDoc.Release( ); return 0; } // Get the root element and check it out long lViewFlags = loadSchemaObject( pDoc->documentElement, ppRootControl ); pDoc.Release( ); return lViewFlags; } long cView::loadSchemaObject( IUnknown *pObject, IUnknown **ppRootControl ) { MSXML::IXMLDOMElementPtr pRoot = pObject; _ASSERTE( pRoot->tagName == _bstr_t( _T( "view" ) ) ); // Get the view parameters _variant_t vIconModule = pRoot->getAttribute( _T( "iconlibrary" ) ), vIcon = pRoot->getAttribute( _T( "icon" ) ), vTitle = pRoot->getAttribute( _T( "title" ) ), vLeft = pRoot->getAttribute( _T( "left" ) ), vTop = pRoot->getAttribute( _T( "top" ) ), vWidth = pRoot->getAttribute( _T( "width" ) ), vHeight = pRoot->getAttribute( _T( "height" ) ), vTrans = pRoot->getAttribute( _T( "transparent" ) ); // We *must* have a title _ASSERTE( vTitle.vt == VT_BSTR ); // Fill this into a view param if( vIconModule.vt == VT_BSTR ) cManager::_p->LoadResourceModule( vIconModule.bstrVal, &m_VP.iconLibrary ); else m_VP.iconLibrary = 0; // GKusnick: Handle no-icon case without asserting. // _ASSERTE( vIcon.vt != VT_NULL ); m_VP.icon = ( vIcon.vt != VT_NULL ) ? static_cast< long >( vIcon ) : 0; // Para: shouldn't add 0x06000000 if there's an iconlibrary if (m_VP.iconLibrary == 0 && m_VP.icon != 0) m_VP.icon += 0x06000000; if(vLeft.vt != VT_NULL) m_VP.left = static_cast< long >(vLeft); else m_VP.left = 25; if(vTop.vt != VT_NULL) m_VP.top = static_cast< long >(vTop); else m_VP.top = 25; if(vWidth.vt == VT_NULL) m_VP.width = 180; else m_VP.width = static_cast< long >(vWidth); if(vHeight.vt == VT_NULL) { SIZE szScreen; cManager::_p->GetScreenSize( &szScreen ); m_VP.height = szScreen.cy/2; } else m_VP.height = static_cast< long >(vHeight); if(vTrans.vt == VT_NULL) m_bTransparent = false; else m_bTransparent = static_cast< bool >( vTrans ); if( m_bTransparent ) m_VP.alpha = 255; else m_VP.alpha = -1; m_VP.label = _bstr_t(vTitle.bstrVal).copy(); // The properly made schema should have a single control child MSXML::IXMLDOMElementPtr pControl = pRoot->selectSingleNode( _T( "control" ) ); _ASSERTE( pControl.GetInterfacePtr() != NULL ); pControl->QueryInterface( ppRootControl ); long lViewFlags = 0; if( m_bTransparent ) lViewFlags |= eTransparent; return lViewFlags; } STDMETHODIMP cView::get_Control(BSTR strName, IControl **pVal) { _ASSERTE( strName != NULL ); _ASSERTE( pVal != NULL ); // Search for a matching control name for( cNamedControlList::iterator i = m_controls.begin(); i != m_controls.end(); ++ i ) { if( i->m_strName == _bstr_t( strName ) ) { *pVal = i->m_pControl; ( *pVal )->AddRef(); return S_OK; } } // The name was not found return E_INVALIDARG; } STDMETHODIMP cView::putref_Control(BSTR strName, IControl *newVal) { _ASSERTE( strName != NULL ); // First look for a matching name for( cNamedControlList::iterator i = m_controls.begin(); i != m_controls.end(); ++ i ) { if( i->m_strName == _bstr_t( strName ) ) { if( newVal == NULL ) m_controls.erase( i ); else i->m_pControl = newVal; return S_OK; } } if( newVal == NULL ) // No value to set return S_OK; // Add in a new record cNamedControl nc; nc.m_strName = strName; nc.m_pControl = newVal; m_controls.push_back( nc ); return S_OK; } STDMETHODIMP cView::LoadControl(ILayerSite *pParent, long nID, IUnknown *pSource, long *pAssignedID) { // Usual parameter validation _ASSERTE( pParent != NULL ); _ASSERTE( pSource != NULL ); _ASSERTE( pAssignedID != NULL ); MSXML::IXMLDOMElementPtr pElement = pSource; // Make sure we're starting from the correct tag name _ASSERTE( pElement->tagName == _bstr_t( _T( "control" ) ) ); // Get the progid and make an instance _variant_t strProgID = pElement->getAttribute( _T( "progid" ) ); _ASSERTE( strProgID.vt == VT_BSTR ); CLSID clsid; HRESULT hRes = ::CLSIDFromProgID( strProgID.bstrVal, &clsid ); _ASSERTE( SUCCEEDED( hRes ) ); CComPtr< ILayer > pChildLayer; hRes = ::CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pChildLayer ) ); _ASSERTE( SUCCEEDED( hRes ) ); // Get some position metrics - note, these are optional and will be // loaded with 0s - this is for cases when the control is formatted // entirely by the parent _variant_t vLeft = pElement->getAttribute( _T( "left" ) ), vTop = pElement->getAttribute( _T( "top" ) ), vWidth = pElement->getAttribute( _T( "width" ) ), vHeight = pElement->getAttribute( _T( "height" ) ), vUnclipped = pElement->getAttribute( _T( "unclipped" ) ), vID = pElement->getAttribute( _T( "ID" ) ); // check for lower case, since all other attributes are lower case. And // Legiondale_Superman can't seem to get it right... if (vID.vt == VT_NULL ) { vID = pElement->getAttribute( _T( "id" ) ); } long nRealID = ( vID.vt == VT_NULL ) ? nID : static_cast< long >( vID ); *pAssignedID = nRealID; POINT pt = { ( vLeft.vt != VT_NULL ) ? static_cast< long >( vLeft ) : 0, ( vTop.vt != VT_NULL ) ? static_cast< long >( vTop ) : 0 }; LayerParams lp = { nRealID, { pt.x, pt.y, pt.x + ( ( vWidth.vt != VT_NULL ) ? static_cast< long >( vWidth ) : 0 ), pt.y + ( ( vHeight.vt != VT_NULL ) ? static_cast< long >( vHeight ) : 0 ) }, ( vUnclipped.vt != VT_NULL ) ? 0 : eRenderClipped }; pParent->CreateChild( &lp, pChildLayer ); // Check if this child is named _variant_t vName = pElement->getAttribute( _T( "name" ) ); if( vName.vt == VT_BSTR ) { // Add the named control CComPtr< IControl > pControl; pChildLayer->QueryInterface( &pControl ); putref_Control( vName.bstrVal, pControl ); } // Ok, the child is made - trick it into loading it's own parameters CComPtr< ILayerSchema > pSchema; if( SUCCEEDED( pChildLayer->QueryInterface( &pSchema ) ) ) pSchema->SchemaLoad( this, pSource ); return S_OK; } STDMETHODIMP cView::LoadSchema(BSTR strXMLSchema) { long nPreviousView; m_pPanel->get_ActiveView( &nPreviousView ); m_pPanel->RemoveView( m_nViewID ); CComPtr< IUnknown > pRootControl; loadSchema( strXMLSchema, &pRootControl ); // Set the bar params m_pRoot->m_pBars->put_Bar( m_nViewID, &m_VP ); long lViewFlags = 0; if( m_bTransparent ) lViewFlags |= eTransparent; // Last, create all the controls m_pPanel->LoadViewEx( m_nViewID, this, pRootControl, lViewFlags ); if( nPreviousView == m_nViewID ) // Reactivate the view m_pRoot->SelectBar( m_nViewID ); return S_OK; } STDMETHODIMP cView::get_Title(BSTR *pVal) { USES_CONVERSION; *pVal = OLE2BSTR( m_VP.label ); return S_OK; } STDMETHODIMP cView::put_Title(BSTR newVal) { _ASSERTE( newVal != NULL ); bool bActivated = m_bActivated; m_VP.label = _bstr_t( newVal ).copy( ); m_pRoot->m_pBars->put_Bar( m_nViewID, &m_VP ); if( bActivated ) m_pPanel->Deactivate(), m_pRoot->SelectBar( m_nViewID ); return S_OK; } STDMETHODIMP cView::Alert() { return S_OK; } STDMETHODIMP cView::SetIcon(long icon, VARIANT iconlibrary) { USES_CONVERSION; m_VP.icon = icon; switch( iconlibrary.vt ) { case VT_ERROR: case VT_EMPTY: case VT_NULL: m_VP.iconLibrary = 0; break; case VT_BSTR: m_VP.iconLibrary = reinterpret_cast< long >( ::GetModuleHandle( OLE2T( iconlibrary.bstrVal ) ) ); break; default: // Try and convert everything else to a number try { _variant_t v = iconlibrary; m_VP.iconLibrary = v; } catch( ... ) { m_VP.iconLibrary = 0; return E_INVALIDARG; } break; } m_pRoot->m_pBars->put_Bar( m_nViewID, &m_VP ); return S_OK; } STDMETHODIMP cView::Activate() { long nActiveView; m_pPanel->get_ActiveView( &nActiveView ); if (nActiveView != m_nViewID) m_pRoot->SelectBar( m_nViewID ); return S_OK; } STDMETHODIMP cView::Deactivate() { m_pPanel->Deactivate(); if(cManager::_p->m_pKeyboard!=NULL) { cManager::_p->m_pKeyboard->sendKeyboardEndCapture( VARIANT_TRUE ); cManager::_p->m_pKeyboard=NULL; } return S_OK; } STDMETHODIMP cView::put_Position(RECT *newVal) { m_VP.left = newVal->left; m_VP.top = newVal->top; m_VP.width = newVal->right; m_VP.height = newVal->bottom; /* Drakier: make sure they aren't being bad little kittens and moving the view offscreen! */ // Drakier: Get the pSite and Screen Size CComPtr< IPluginSite > pPlugin; CComPtr< IACHooks > pHooks; m_pRoot->m_pSite->get_PluginSite( &pPlugin ); SIZE szScreen, sz; pPlugin->GetScreenSize( &sz ); szScreen.cx = sz.cx; szScreen.cy = sz.cy; long lX = sz.cx, lY = sz.cy; HRESULT hW = S_FALSE, hH = S_FALSE; // Drakier: if we are not in the container, get the 3D Area if ( !cManager::_p->m_bContainer ) { pPlugin->get_Hooks( &pHooks ); hH = pHooks->get_Area3DHeight( &lY ); hW = pHooks->get_Area3DWidth( &lX ); pHooks.Release(); } pPlugin.Release(); // Drakier: if we are in the container, or the 3D area's are NULL if ( (cManager::_p->m_bContainer) || (hW != S_OK) || (hH != S_OK) ) { szScreen.cx = sz.cx - 308; // 308 = PANEL_SIZE szScreen.cy = sz.cy; } else // Drakier: If everything comes out right and we are not in container { if( (hW == S_OK) && (lX > 200) && (lX < 2000) ) szScreen.cx = lX; if( (hH == S_OK) && (lY > 200) && (lY < 2000) ) szScreen.cy = lY; } if ( (szScreen.cx > 200) && (szScreen.cx < 2000) && (szScreen.cy > 200) && (szScreen.cy < 2000) ) { if ( (m_VP.left + m_VP.width) > szScreen.cx ) m_VP.left = szScreen.cx - m_VP.width; if ( (m_VP.top + m_VP.height) > szScreen.cy ) m_VP.top = szScreen.cy - m_VP.height; if ( m_VP.left < 0 ) m_VP.left = 0; if ( m_VP.top < 0 ) m_VP.top = 0; long nActiveView; m_pPanel->get_ActiveView( &nActiveView ); if( nActiveView == m_nViewID ) m_pPanel->ActivateView(m_nViewID, &m_VP, (long*)this); } return S_OK; } STDMETHODIMP cView::get_Position(RECT *pVal) { pVal->left = m_VP.left; pVal->top = m_VP.top; pVal->right = m_VP.width; pVal->bottom = m_VP.height; return S_OK; } STDMETHODIMP cView::get_Alpha(long *pVal) { if( pVal == NULL ) return E_POINTER; if (m_bTransparent) { *pVal = m_lOldAlpha ; } else { *pVal = m_VP.alpha; } return S_OK; } STDMETHODIMP cView::put_Alpha(long Alpha) { if( m_bTransparent ) return S_FALSE; m_VP.alpha = Alpha; long nActiveView; m_pPanel->get_ActiveView( &nActiveView ); if( nActiveView == m_nViewID ) m_pPanel->ActivateView(m_nViewID, &m_VP, (long*)this); return S_OK; } STDMETHODIMP cView::get_Activated(VARIANT_BOOL *pVal) { *pVal = ( m_bActivated ? VARIANT_TRUE : VARIANT_FALSE ); return S_OK; } STDMETHODIMP cView::put_Activated(VARIANT_BOOL newVal) { if( newVal == VARIANT_FALSE ) return Deactivate(); else return Activate(); } STDMETHODIMP cView::get_Transparent(VARIANT_BOOL *pVal) { *pVal = ( m_bTransparent ? VARIANT_TRUE : VARIANT_FALSE ); return S_OK; } STDMETHODIMP cView::put_Transparent(VARIANT_BOOL newVal) { if( newVal == VARIANT_FALSE ) { if( !m_bTransparent ) return S_OK; m_bTransparent = false; m_VP.alpha = m_lOldAlpha; m_pPanel->put_Transparent( VARIANT_FALSE ); } else { if( m_bTransparent ) return S_OK; m_bTransparent = true; m_lOldAlpha = m_VP.alpha; m_VP.alpha = 255; m_pPanel->put_Transparent( VARIANT_TRUE ); } return S_OK; }