Initial commit: Complete open-source Decal rebuild

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>
This commit is contained in:
erik 2026-02-08 18:27:56 +01:00
commit d1442e3747
1382 changed files with 170725 additions and 0 deletions

View file

@ -0,0 +1,220 @@
// ListView.cpp : Implementation of cListView
#include "stdafx.h"
#include "DecalControls.h"
#include "ListView.h"
#include "List.h"
/////////////////////////////////////////////////////////////////////////////
// cListView
cListView::cListView()
: m_nRowHeight( 20 ),
m_nRowCache( 0 ),
m_nValidFrom( 0 ),
m_nValidTo( 0 )
{
}
STDMETHODIMP cListView::put_Area(LPSIZE newVal)
{
RECT rc = { 0, 0, newVal->cx, newVal->cy };
m_pSite->put_Position( &rc );
return S_OK;
}
STDMETHODIMP cListView::SetCacheInfo(long nRowHeight, long nRowsToCache)
{
m_nRowHeight = nRowHeight;
m_nRowCache = nRowsToCache;
m_pSite->Reformat();
return S_OK;
}
void cListView::onCreate()
{
CComPtr< IPluginSite > pPlugin;
m_pSite->get_PluginSite( &pPlugin );
pPlugin->LoadBitmapPortal( 0x0600128A, &m_pBackground );
m_pSite->put_Transparent( VARIANT_FALSE );
}
void cListView::onDestroy()
{
m_pBackground.Release();
if( m_pCache.p != NULL )
m_pCache.Release();
}
STDMETHODIMP cListView::Reformat()
{
RECT rcPos;
m_pSite->get_Position( &rcPos );
SIZE szCache = { rcPos.right - rcPos.left, m_nRowHeight * m_nRowCache };
if( m_pCache.p != NULL )
m_pCache->put_Size( &szCache );
else
{
CComPtr< IPluginSite > pPlugin;
m_pSite->get_PluginSite( &pPlugin );
pPlugin->CreateCanvas( &szCache, &m_pCache );
}
_ASSERTMEM( _CrtCheckMemory( ) );
return S_OK;
}
STDMETHODIMP cListView::Render(ICanvas *pCanvas)
{
_ASSERTMEM( _CrtCheckMemory( ) );
// First, draw the Background pattern
VARIANT_BOOL bLost;
m_pCache->get_WasLost( &bLost );
if( bLost )
// There is no valid range - we must redraw
// the entire rowset
m_nValidFrom = m_nValidTo;
ClipParams cp;
pCanvas->GetClipParams( &cp );
SIZE szCache;
m_pCache->get_Size( &szCache );
// We have the clipping rectangle now - calculate the range
// of rows we want to draw
long nDrawFrom = cp.org.y / m_nRowHeight,
nDrawTo = nDrawFrom + m_nRowCache,
nRowCount = m_pList->m_rows.size();
// Ok, now draw all of the rows either out of range
// or invalid
for( long nDraw = nDrawFrom; nDraw < nDrawTo; ++ nDraw )
{
// Determine how much we need to draw
bool bHasData = ( nDraw >= 0 && nDraw < nRowCount );
if( nDraw < m_nValidFrom || nDraw >= m_nValidTo || ( bHasData && m_pList->m_rows[ nDraw ].m_bInvalid ) )
{
// Redraw this row
long nRowPos = nDraw % m_nRowCache;
RECT rcRow = { 0, nRowPos * m_nRowHeight, szCache.cx, ( nRowPos + 1 ) * m_nRowHeight };
// Fill the background with the background image
POINT ptBackgroundOrg = { 0, nDraw * m_nRowHeight };
m_pBackground->PatBlt( m_pCache, &rcRow, &ptBackgroundOrg );
if( bHasData )
{
// This row is visible and there's data - so use the
// column objects to render the data
for( cList::cColumnList::iterator i_col = m_pList->m_cols.begin(); i_col != m_pList->m_cols.end(); ++ i_col )
{
RECT rcCell = { i_col->m_nLeft, rcRow.top, i_col->m_nRight, rcRow.bottom };
VARIANT_BOOL bVisible;
m_pCache->PushClipRect( &rcCell, &bVisible );
// All our clippings should be completely visible
_ASSERTE( bVisible );
long nColor;
POINT ptCell = { i_col - m_pList->m_cols.begin(), nDraw };
get_Color(ptCell.x, ptCell.y, &nColor);
i_col->m_pColumn->Render( m_pCache, &ptCell, nColor);
m_pCache->PopClipRect();
_ASSERTMEM( _CrtCheckMemory( ) );
}
m_pList->m_rows[ nDraw ].m_bInvalid = false;
}
}
}
// Now that our cache is updated, we can tranfer it to the surface
m_nValidFrom = nDrawFrom;
m_nValidTo = nDrawTo;
long nBltFrom = nDrawFrom % m_nRowCache;
RECT rcTop = { 0, nBltFrom * m_nRowHeight, szCache.cx, m_nRowHeight * m_nRowCache };
POINT ptDest = { 0, nDrawFrom * m_nRowHeight };
pCanvas->Blt( &rcTop, m_pCache, &ptDest );
if( nBltFrom != 0 )
{
// Transfer the bottom part
RECT rcBottom = { 0, 0, szCache.cx, nBltFrom * m_nRowHeight };
POINT ptDestBottom = { 0, ( nDrawFrom + m_nRowCache - nBltFrom ) * m_nRowHeight };
pCanvas->Blt( &rcBottom, m_pCache, &ptDestBottom );
}
_ASSERTMEM( _CrtCheckMemory( ) );
return S_OK;
}
STDMETHODIMP cListView::MouseDown( MouseState *pMS )
{
// Hit test to find what cell
POINT ptHit = { 0, pMS->client.y / m_nRowHeight };
if( ptHit.y >= m_pList->m_rows.size() )
// We did not hit any rows
return S_OK;
for( cList::cColumnList::iterator i_col = m_pList->m_cols.begin(); i_col != m_pList->m_cols.end(); ++ i_col )
{
if( pMS->client.x >= i_col->m_nLeft && pMS->client.x < i_col->m_nRight )
{
ptHit.x = ( i_col - m_pList->m_cols.begin() );
i_col->m_pColumn->Activate( &ptHit );
long nID;
m_pList->m_pSite->get_ID( &nID );
m_pList->Fire_Change( nID, ptHit.x, ptHit.y );
break;
}
}
return S_OK;
}
STDMETHODIMP cListView::InvalidateFrom(long nRow)
{
if( nRow < m_nValidTo )
m_nValidTo = nRow;
if( nRow < m_nValidFrom )
m_nValidFrom = nRow;
return S_OK;
}
STDMETHODIMP cListView::get_Color(long nCol, long nRow, long *pVal)
{
m_pList->get_Color(nCol, nRow, pVal);
return S_OK;
}
STDMETHODIMP cListView::put_Color(long nCol, long nRow, long newVal)
{
m_pList->put_Color(nCol, nRow, newVal);
return S_OK;
}