All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
197 lines
5.2 KiB
C++
197 lines
5.2 KiB
C++
// BorderLayout.cpp : Implementation of cBorderLayout
|
|
#include "stdafx.h"
|
|
#include "DecalControls.h"
|
|
#include "BorderLayout.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// cBorderLayout
|
|
|
|
void cBorderLayout::onSchemaLoad( IView *pView, MSXML::IXMLDOMElementPtr &pElement )
|
|
{
|
|
static _bstr_t _strEdge = _T( "border" ),
|
|
_strCenter = _T( "center" );
|
|
static _variant_t
|
|
_strLeft = _T( "left" ),
|
|
_strRight = _T( "right" ),
|
|
_strTop = _T( "top" ),
|
|
_strBottom = _T( "bottom" );
|
|
|
|
// Walk through the list of children - select all elements
|
|
MSXML::IXMLDOMElementPtr pChild;
|
|
for( MSXML::IXMLDOMNodeListPtr pChildren = pElement->selectNodes( _T( "*" ) );
|
|
( pChild = pChildren->nextNode() ).GetInterfacePtr() != NULL; )
|
|
{
|
|
if( pChild->tagName == _strEdge )
|
|
{
|
|
// Attempt to extract the edge indicator and the size indicator
|
|
_variant_t vEdge = pChild->getAttribute( _T( "edge" ) ),
|
|
vSize = pChild->getAttribute( _T( "size" ) );
|
|
|
|
_ASSERTE( vEdge.vt != VT_NULL );
|
|
_ASSERTE( vSize.vt != VT_NULL );
|
|
|
|
// Got values, check if they're good
|
|
eBorderEdge eEdge;
|
|
|
|
if( _strLeft == vEdge )
|
|
eEdge = eEdgeLeft;
|
|
else if( vEdge == _strRight )
|
|
eEdge = eEdgeRight;
|
|
else if( vEdge == _strTop )
|
|
eEdge = eEdgeTop;
|
|
else if( vEdge == _strBottom )
|
|
eEdge = eEdgeBottom;
|
|
#ifdef _DEBUG
|
|
else
|
|
// Invalid value here
|
|
_ASSERTE( FALSE );
|
|
#endif
|
|
|
|
// Convert the size
|
|
try
|
|
{
|
|
long nSize = vSize;
|
|
|
|
// Cannot have a 0 or negative edge size
|
|
_ASSERTE( nSize > 0 );
|
|
|
|
cEdgePlacement ep = { eEdge, nSize, loadChildControl( pView, pChild->selectSingleNode( _T( "control" ) ) ) };
|
|
m_edges.push_back( ep );
|
|
}
|
|
catch( ... )
|
|
{
|
|
// The size could no be converted to a long value
|
|
_ASSERTE( FALSE );
|
|
}
|
|
}
|
|
else if( pChild->tagName == _strCenter )
|
|
{
|
|
// Make sure there isn't a center already created
|
|
_ASSERTE( m_nCenterID == -1 );
|
|
|
|
m_nCenterID = loadChildControl( pView, pChild->selectSingleNode( _T( "control" ) ) );
|
|
}
|
|
#ifdef _DEBUG
|
|
else
|
|
// This is an invalid child element type
|
|
_ASSERTE( FALSE );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void cBorderLayout::onChildDestroy( long nID )
|
|
{
|
|
// Check if this is the center
|
|
if( nID == m_nCenterID )
|
|
{
|
|
m_nCenterID = -1;
|
|
m_pSite->Reformat();
|
|
return;
|
|
}
|
|
|
|
// Check if it on an edge
|
|
for( cEdgePlacementList::iterator i = m_edges.begin(); i != m_edges.end(); ++ i )
|
|
{
|
|
if( i->m_nID == nID )
|
|
{
|
|
m_edges.erase( i );
|
|
m_pSite->Reformat();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP cBorderLayout::CreateEdge(eBorderEdge eEdge, long nSize, ILayer *pSink)
|
|
{
|
|
_ASSERTE( nSize > 0 );
|
|
_ASSERTE( pSink != NULL );
|
|
|
|
LayerParams lp = { dispenseID(), { 0, 0, 0, 0 }, eRenderClipped };
|
|
m_pSite->CreateChild( &lp, pSink );
|
|
|
|
cEdgePlacement ep = { eEdge, nSize, lp.ID };
|
|
m_edges.push_back( ep );
|
|
m_pSite->Reformat();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cBorderLayout::CreateCenter(ILayer *pSink)
|
|
{
|
|
_ASSERTE( m_nCenterID == -1 );
|
|
|
|
LayerParams lp = { dispenseID(), { 0, 0, 0, 0 }, eRenderClipped };
|
|
m_pSite->CreateChild( &lp, pSink );
|
|
|
|
m_nCenterID = lp.ID;
|
|
m_pSite->Reformat();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cBorderLayout::Reformat()
|
|
{
|
|
// Walk through the list of edges in order and
|
|
// set their positions
|
|
|
|
RECT rcLayer;
|
|
m_pSite->get_Position( &rcLayer );
|
|
|
|
RECT rcClient = { 0, 0, rcLayer.right - rcLayer.left, rcLayer.bottom - rcLayer.top };
|
|
|
|
for( cEdgePlacementList::iterator i = m_edges.begin(); i != m_edges.end(); ++ i )
|
|
{
|
|
RECT rcPosition = rcClient;
|
|
|
|
switch( i->m_edge )
|
|
{
|
|
case eEdgeLeft:
|
|
rcPosition.right = rcPosition.left + i->m_nSize;
|
|
rcClient.left += i->m_nSize;
|
|
break;
|
|
|
|
case eEdgeTop:
|
|
rcPosition.bottom = rcPosition.top + i->m_nSize;
|
|
rcClient.top += i->m_nSize;
|
|
break;
|
|
|
|
case eEdgeRight:
|
|
rcPosition.left = rcPosition.right - i->m_nSize;
|
|
rcClient.right -= i->m_nSize;
|
|
break;
|
|
|
|
case eEdgeBottom:
|
|
rcPosition.top = rcPosition.bottom - i->m_nSize;
|
|
rcClient.bottom -= i->m_nSize;
|
|
break;
|
|
|
|
default:
|
|
// Invalid edge value
|
|
_ASSERTE( FALSE );
|
|
}
|
|
|
|
// Sanity checks to make sure we haven't overrun our area
|
|
//_ASSERTE( rcClient.bottom > rcClient.top );
|
|
_ASSERTE( rcClient.right > rcClient.left );
|
|
_ASSERTE( rcPosition.bottom > rcPosition.top );
|
|
_ASSERTE( rcPosition.right > rcPosition.left );
|
|
|
|
CComPtr< ILayerSite > pChild;
|
|
HRESULT hRes = m_pSite->get_Child( i->m_nID, ePositionByID, &pChild );
|
|
_ASSERTE( SUCCEEDED( hRes ) );
|
|
|
|
pChild->put_Position( &rcPosition );
|
|
}
|
|
|
|
if( m_nCenterID != -1 )
|
|
{
|
|
CComPtr< ILayerSite > pChild;
|
|
HRESULT hRes = m_pSite->get_Child( m_nCenterID, ePositionByID, &pChild );
|
|
_ASSERTE( SUCCEEDED( hRes ) );
|
|
|
|
pChild->put_Position( &rcClient );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|