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>
220 lines
5.5 KiB
C++
220 lines
5.5 KiB
C++
// 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;
|
|
}
|