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:
commit
d1442e3747
1382 changed files with 170725 additions and 0 deletions
656
Native/DecalControls/List.cpp
Normal file
656
Native/DecalControls/List.cpp
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
// List.cpp : Implementation of cList
|
||||
#include "stdafx.h"
|
||||
#include "DecalControls.h"
|
||||
#include "List.h"
|
||||
|
||||
#include "ListView.h"
|
||||
|
||||
enum eListChild
|
||||
{
|
||||
eListScroller = 1,
|
||||
eListView = 1000
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// cList
|
||||
|
||||
cList::cRow::cRow( long nDataWidth )
|
||||
: m_pData( new VARIANT[ nDataWidth ] ),
|
||||
m_pEndData( m_pData + nDataWidth ),
|
||||
m_bInvalid( true ),
|
||||
m_colors( NULL ) /* cyn - 07/08/2002 */
|
||||
{
|
||||
for( VARIANT *i_var = m_pData; i_var != m_pEndData; ++ i_var )
|
||||
::VariantInit( i_var );
|
||||
|
||||
}
|
||||
|
||||
cList::cRow::cRow( const cRow &row )
|
||||
: m_pData( row.m_pData ),
|
||||
m_pEndData( row.m_pEndData ),
|
||||
m_bInvalid( row.m_bInvalid ),
|
||||
m_colors( row.m_colors ) /* cyn - 07/08/2002 -- This is the real fix, the rest of */
|
||||
/* the changes just make it faster */
|
||||
{
|
||||
_ASSERTE( _CrtIsValidHeapPointer( m_pData ) );
|
||||
row.m_pData = NULL;
|
||||
row.m_colors = NULL;
|
||||
}
|
||||
|
||||
cList::cRow::~cRow()
|
||||
{
|
||||
if( m_pData != NULL )
|
||||
{
|
||||
_ASSERTE( _CrtIsValidHeapPointer( m_pData ) );
|
||||
for( VARIANT *i_var = m_pData; i_var != m_pEndData; ++ i_var )
|
||||
{
|
||||
HRESULT hRes = ::VariantClear( i_var );
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
}
|
||||
|
||||
delete[] m_pData;
|
||||
}
|
||||
|
||||
if (m_colors) { /* cyn - 07/08/2002 */
|
||||
delete[] m_colors;
|
||||
}
|
||||
}
|
||||
|
||||
cList::cRow &cList::cRow::operator =( const cRow &row )
|
||||
{
|
||||
|
||||
|
||||
// Clear out our current data - if any
|
||||
if( m_pData != NULL )
|
||||
{
|
||||
_ASSERTE( _CrtIsValidHeapPointer( m_pData ) );
|
||||
for( VARIANT *i_var = m_pData; i_var != m_pEndData; ++ i_var )
|
||||
{
|
||||
HRESULT hRes = ::VariantClear( i_var );
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
}
|
||||
|
||||
delete[] m_pData;
|
||||
m_pData = NULL;
|
||||
}
|
||||
|
||||
_ASSERTE( _CrtIsValidHeapPointer( row.m_pData ) );
|
||||
|
||||
m_pData = row.m_pData;
|
||||
m_pEndData = row.m_pEndData;
|
||||
m_bInvalid = row.m_bInvalid;
|
||||
|
||||
if (m_colors) { /* cyn - 07/08/2002 */
|
||||
delete[] m_colors;
|
||||
}
|
||||
m_colors = row.m_colors;
|
||||
row.m_colors = NULL;
|
||||
|
||||
row.m_pData = NULL;
|
||||
|
||||
_ASSERTMEM( _CrtCheckMemory() );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::AddColumn(IListColumn *pNewColumn, long *nIndex)
|
||||
{
|
||||
_ASSERTE( pNewColumn != NULL );
|
||||
_ASSERTE( nIndex != NULL );
|
||||
|
||||
// We can only add columns before there are data rows
|
||||
_ASSERTE( m_rows.size() == 0 );
|
||||
|
||||
// Looking good, make up the record
|
||||
cColumn c;
|
||||
c.m_pColumn = pNewColumn;
|
||||
c.m_nDataLeft = ( m_cols.size() == 0 ) ? 0 : m_cols.back().m_nDataRight;
|
||||
|
||||
CComPtr< IPluginSite > pPluginSite;
|
||||
m_pSite->get_PluginSite( &pPluginSite );
|
||||
|
||||
long nDataSize;
|
||||
pNewColumn->get_DataColumns( &nDataSize );
|
||||
c.m_nDataRight = c.m_nDataLeft + nDataSize;
|
||||
|
||||
pNewColumn->Initialize( this, pPluginSite );
|
||||
|
||||
CComPtr< ILayerMouse > pMouse;
|
||||
c.m_bSupportsMouse = !!SUCCEEDED( pNewColumn->QueryInterface( &pMouse ) );
|
||||
|
||||
m_cols.push_back( c );
|
||||
|
||||
// Reformat will fill in column lefts and rights
|
||||
m_pSite->Reformat();
|
||||
|
||||
*nIndex = ( m_cols.size() - 1 );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::AddRow(long *pnNewIndex)
|
||||
{
|
||||
_ASSERTE( pnNewIndex != NULL );
|
||||
|
||||
// There must be at least one column defined
|
||||
_ASSERTE( m_cols.size() > 0 );
|
||||
|
||||
m_rows.push_back( cRow( m_cols.back().m_nDataRight ) );
|
||||
long nSize = m_rows.size();
|
||||
|
||||
Reformat();
|
||||
m_pSite->Reformat();
|
||||
|
||||
if( m_bAutoScroll == true )
|
||||
{
|
||||
POINT ptCurrent;
|
||||
m_pScroller->get_Offset( &ptCurrent );
|
||||
|
||||
ptCurrent.y = m_rows.size();
|
||||
|
||||
m_pScroller->ScrollTo( &ptCurrent );
|
||||
|
||||
Reformat();
|
||||
m_pSite->Reformat();
|
||||
}
|
||||
|
||||
*pnNewIndex = ( nSize - 1 );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::DeleteRow(long nIndex)
|
||||
{
|
||||
_ASSERTE( nIndex >= 0 );
|
||||
_ASSERTE( nIndex < m_rows.size() );
|
||||
|
||||
m_rows.erase( m_rows.begin() + nIndex );
|
||||
|
||||
// Start at that index and invalidate all rows below that point
|
||||
m_pView->InvalidateFrom( nIndex );
|
||||
for( cRowList::iterator i_row = m_rows.begin() + nIndex; i_row != m_rows.end(); ++ i_row )
|
||||
i_row->m_bInvalid = true;
|
||||
|
||||
m_pSite->Invalidate();
|
||||
m_pSite->Reformat();
|
||||
|
||||
POINT offset;
|
||||
::memset (&offset, 0, sizeof (offset));
|
||||
|
||||
m_pScroller->get_Offset (&offset);
|
||||
|
||||
if (offset.y > nIndex )
|
||||
{
|
||||
// TODO: This isn't perfect, if items are removed from the bottom of the list when
|
||||
// you're scrolled to the middle, this will cause it to scroll up a line. It does
|
||||
// solve the problem of lists 'losing' items when the thumb goes away though.
|
||||
|
||||
// Note by Haz - I changed the above from if( offset.y > 0 ) - seems to fix problem :)
|
||||
offset.y--;
|
||||
m_pScroller->ScrollTo (&offset);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_Data(long nX, long nY, long nSubValue, VARIANT *pVal)
|
||||
{
|
||||
_ASSERTE( m_cols.size() > 0 );
|
||||
_ASSERTE( nX >= 0 );
|
||||
_ASSERTE( nX < m_cols.back().m_nDataRight );
|
||||
_ASSERTE( nSubValue >= 0 );
|
||||
_ASSERTE( nSubValue < ( m_cols[ nX ].m_nDataRight - m_cols[ nX ].m_nDataLeft ) );
|
||||
_ASSERTE( nY >= 0 );
|
||||
_ASSERTE( nY < m_rows.size() );
|
||||
_ASSERTE( pVal != NULL );
|
||||
|
||||
cRow &rowData = m_rows[ nY ];
|
||||
HRESULT hRes = ::VariantCopy( pVal, rowData.m_pData + ( m_cols[ nX ].m_nDataLeft + nSubValue ) );
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::put_Data(long nX, long nY, long nSubValue, VARIANT *newVal)
|
||||
{
|
||||
_ASSERTE( m_cols.size() > 0 );
|
||||
_ASSERTE( nX >= 0 );
|
||||
_ASSERTE( nX < m_cols.back().m_nDataRight );
|
||||
_ASSERTE( nSubValue >= 0 );
|
||||
_ASSERTE( nSubValue < ( m_cols[ nX ].m_nDataRight - m_cols[ nX ].m_nDataLeft ) );
|
||||
_ASSERTE( nY >= 0 );
|
||||
_ASSERTE( nY < m_rows.size() );
|
||||
_ASSERTE( newVal != NULL );
|
||||
|
||||
if( nY >= m_rows.size() )
|
||||
return E_FAIL;
|
||||
|
||||
cRow &rowData = m_rows[ nY ];
|
||||
|
||||
long lDataColumns = 0;
|
||||
m_cols[ nX ].m_pColumn->get_DataColumns( &lDataColumns );
|
||||
|
||||
if( nSubValue > lDataColumns )
|
||||
return E_FAIL;
|
||||
|
||||
HRESULT hRes = ::VariantCopy( rowData.m_pData + ( m_cols[ nX ].m_nDataLeft + nSubValue ), newVal );
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
rowData.m_bInvalid = true;
|
||||
|
||||
m_pSite->Invalidate();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_CellRect(LPPOINT pt, LPRECT pVal)
|
||||
{
|
||||
_ASSERTE( pt != NULL );
|
||||
_ASSERTE( m_cols.size() > 0 );
|
||||
_ASSERTE( pt->x >= 0 );
|
||||
_ASSERTE( pt->x < m_cols.back().m_nDataRight );
|
||||
_ASSERTE( pt->y >= 0 );
|
||||
_ASSERTE( pt->y < m_rows.size() );
|
||||
_ASSERTE( pVal != NULL );
|
||||
|
||||
pVal->top = pt->y * m_nRowHeight;
|
||||
pVal->bottom = ( pt->y + 1 ) * m_nRowHeight;
|
||||
pVal->left = m_cols[ pt->x ].m_nLeft;
|
||||
pVal->right = m_cols[ pt->y ].m_nRight;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void cList::onCreate()
|
||||
{
|
||||
// Create the scoller and the scroller client object
|
||||
CComPtr< ILayer > pScrollerLayer;
|
||||
|
||||
HRESULT hRes = ::CoCreateInstance( CLSID_Scroller, NULL, CLSCTX_INPROC_SERVER,
|
||||
__uuidof( ILayer ), reinterpret_cast< void ** >( &pScrollerLayer ) );
|
||||
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
|
||||
// Will reposition on reformat
|
||||
LayerParams p = { eListScroller, { 0, 0, 0, 0 }, eRenderClipped };
|
||||
|
||||
m_pSite->CreateChild( &p, pScrollerLayer );
|
||||
pScrollerLayer->QueryInterface( &m_pScroller );
|
||||
|
||||
CComObject< cListView > *pView;
|
||||
CComObject< cListView >::CreateInstance( &pView );
|
||||
|
||||
m_pScroller->CreateClient( pView );
|
||||
m_pView = pView;
|
||||
|
||||
// Configure the scroller
|
||||
|
||||
SIZE szIncrement = { 100, 20 };
|
||||
m_pScroller->put_Increments( &szIncrement );
|
||||
m_pScroller->put_HorizontalEnabled( VARIANT_FALSE );
|
||||
m_pScroller->put_VerticalEnabled( VARIANT_TRUE );
|
||||
|
||||
pView->m_pList = this;
|
||||
|
||||
m_pSite->put_Transparent( VARIANT_FALSE );
|
||||
}
|
||||
|
||||
void cList::onDestroy()
|
||||
{
|
||||
// Release all of our references
|
||||
m_pView.Release();
|
||||
m_pScroller.Release();
|
||||
|
||||
// Kill the data
|
||||
m_cols.clear();
|
||||
m_rows.clear();
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::Reformat()
|
||||
{
|
||||
// Recalculate the column widths and reposition the child control
|
||||
RECT rc;
|
||||
m_pSite->get_Position( &rc );
|
||||
|
||||
RECT rcScroller = { 0, 0, rc.right - rc.left, rc.bottom - rc.top };
|
||||
CComPtr< ILayerSite > pScrollerSite;
|
||||
HRESULT hRes = m_pSite->get_Child( eListScroller, ePositionByID, &pScrollerSite );
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
|
||||
pScrollerSite->put_Position( &rcScroller );
|
||||
|
||||
SIZE szClient;
|
||||
m_pScroller->get_Viewport( &szClient );
|
||||
|
||||
// Ok, setup the list view objects (note there is cache for a partial row at the top and bottom)
|
||||
m_pView->SetCacheInfo( m_nRowHeight, ( szClient.cy / m_nRowHeight ) + 2 );
|
||||
|
||||
szClient.cy = m_nRowHeight * m_rows.size();
|
||||
|
||||
m_pScroller->put_Area( &szClient );
|
||||
|
||||
// Last, calculate the column widths
|
||||
long nFixedWidthsTotal = 0,
|
||||
nVariableCount = 0;
|
||||
|
||||
// First pass adds up the fixed widths
|
||||
{
|
||||
for( cColumnList::iterator i = m_cols.begin(); i != m_cols.end(); ++ i )
|
||||
{
|
||||
VARIANT_BOOL bFixed;
|
||||
i->m_pColumn->get_FixedWidth( &bFixed );
|
||||
|
||||
if( bFixed )
|
||||
{
|
||||
long nWidth;
|
||||
i->m_pColumn->get_Width( &nWidth );
|
||||
|
||||
nFixedWidthsTotal += nWidth;
|
||||
}
|
||||
else
|
||||
++ nVariableCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Next pass sets the widths
|
||||
//_ASSERTE( nFixedWidthsTotal < szClient.cx );
|
||||
|
||||
long nPosition = 0;
|
||||
|
||||
for( cColumnList::iterator i = m_cols.begin(); i != m_cols.end(); ++ i )
|
||||
{
|
||||
VARIANT_BOOL bFixed;
|
||||
i->m_pColumn->get_FixedWidth( &bFixed );
|
||||
|
||||
i->m_nLeft = nPosition;
|
||||
|
||||
if( bFixed )
|
||||
{
|
||||
long nWidth;
|
||||
i->m_pColumn->get_Width( &nWidth );
|
||||
i->m_nRight = i->m_nLeft + nWidth;
|
||||
}
|
||||
else
|
||||
i->m_nRight = i->m_nLeft + ( szClient.cx - nFixedWidthsTotal ) / nVariableCount;
|
||||
|
||||
nPosition = i->m_nRight;
|
||||
}
|
||||
|
||||
_ASSERTMEM( _CrtCheckMemory( ) );
|
||||
|
||||
_ASSERT(0==0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::put_RowEstimate(long newVal)
|
||||
{
|
||||
m_rows.reserve( newVal );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::SchemaLoad(IView *, IUnknown *pSchema)
|
||||
{
|
||||
MSXML::IXMLDOMElementPtr pElement = pSchema;
|
||||
|
||||
_variant_t vRowHeight = pElement->getAttribute( _T( "rowheight" ) );
|
||||
|
||||
if( vRowHeight.vt != VT_NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
m_nRowHeight = static_cast< long >( vRowHeight );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Type conversion error
|
||||
_ASSERTE( FALSE );
|
||||
}
|
||||
}
|
||||
else
|
||||
m_nRowHeight = 20;
|
||||
|
||||
_variant_t vAutoScroll = pElement->getAttribute( _T( "autoscroll" ) );
|
||||
if( vAutoScroll.vt != VT_NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
m_bAutoScroll = static_cast< bool >( vAutoScroll );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Type conversion error
|
||||
_ASSERTE( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Walk the list of columns under this element
|
||||
MSXML::IXMLDOMElementPtr pColumn;
|
||||
for( MSXML::IXMLDOMNodeListPtr pColumns = pElement->selectNodes( _T( "column" ) ); ( pColumn = pColumns->nextNode() ).GetInterfacePtr() != NULL; )
|
||||
{
|
||||
_variant_t vProgID = pColumn->getAttribute( _T( "progid" ) );
|
||||
|
||||
_ASSERTE( vProgID.vt == VT_BSTR );
|
||||
|
||||
CLSID clsid;
|
||||
HRESULT hRes = ::CLSIDFromProgID( vProgID.bstrVal, &clsid );
|
||||
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
|
||||
// Looking good, create the column object
|
||||
CComPtr< IListColumn > pColumnInst;
|
||||
|
||||
hRes = ::CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_IListColumn,
|
||||
reinterpret_cast< void ** >( &pColumnInst ) );
|
||||
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
|
||||
// Have the column load any special internal values
|
||||
pColumnInst->SchemaLoad( pColumn );
|
||||
|
||||
long nIndex;
|
||||
AddColumn( pColumnInst, &nIndex );
|
||||
}
|
||||
|
||||
SIZE szIncrement = { 100, m_nRowHeight };
|
||||
m_pScroller->put_Increments( &szIncrement );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_Count( long *pnCount )
|
||||
{
|
||||
_ASSERTE( pnCount != NULL );
|
||||
|
||||
*pnCount = m_rows.size();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_CountCols( long *pnCount )
|
||||
{
|
||||
_ASSERTE( pnCount != NULL );
|
||||
|
||||
*pnCount = m_cols.size();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::Clear()
|
||||
{
|
||||
m_rows.clear();
|
||||
m_pView->InvalidateFrom( 0 );
|
||||
|
||||
m_pScroller->ResetScroller();
|
||||
|
||||
m_pSite->Reformat();
|
||||
m_pSite->Invalidate();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::InsertRow(long lIndex)
|
||||
{
|
||||
_ASSERTE (lIndex >= 0);
|
||||
// There must be at least one column defined
|
||||
_ASSERTE( m_cols.size() > 0 );
|
||||
|
||||
cRowList::iterator it = m_rows.begin ();
|
||||
|
||||
if (lIndex > 0)
|
||||
{
|
||||
it += lIndex;
|
||||
}
|
||||
|
||||
m_rows.insert( it, cRow( m_cols.back().m_nDataRight ) );
|
||||
|
||||
// Start at that index and invalidate all rows below that point
|
||||
m_pView->InvalidateFrom( lIndex );
|
||||
for( cRowList::iterator i_row = m_rows.begin() + lIndex; i_row != m_rows.end(); ++ i_row )
|
||||
{
|
||||
i_row->m_bInvalid = true;
|
||||
}
|
||||
|
||||
m_pSite->Invalidate();
|
||||
m_pSite->Reformat();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::put_ColumnWidth(long nColumn, long nWidth)
|
||||
{
|
||||
m_cols[ nColumn ].m_pColumn->put_Width(nWidth);
|
||||
m_pSite->Invalidate();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_ColumnWidth(long nColumn, long *nWidth)
|
||||
{
|
||||
m_cols[ nColumn ].m_pColumn->get_Width(nWidth);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_Color(long nX, long nY, long *pVal)
|
||||
{
|
||||
|
||||
if (!pVal) { /* cyn - 07/08/2002 */
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*pVal = 0x00FFFFFF;
|
||||
cRow &rowData = m_rows[nY];
|
||||
|
||||
if (nX >= m_cols.size()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (rowData.m_colors) {
|
||||
if (rowData.m_colors[nX]) {
|
||||
*pVal = rowData.m_colors[nX];
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::put_Color(long nX, long nY, long newVal)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nX >= m_cols.size()) { /* cyn - 07/08/2002 */
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
cRow &rowData = m_rows[nY];
|
||||
|
||||
if (!rowData.m_colors) {
|
||||
i = m_cols.size();
|
||||
rowData.m_colors = new long[ i ];
|
||||
if (!rowData.m_colors) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// Madar 9/8/2002: Initialize colors to white.
|
||||
for (long loop = 0; loop < m_cols.size(); ++loop) {
|
||||
rowData.m_colors[loop] = 0x00ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
rowData.m_colors[nX] = newVal;
|
||||
|
||||
m_pSite->Invalidate();
|
||||
rowData.m_bInvalid = true;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_AutoScroll(VARIANT_BOOL *pVal)
|
||||
{
|
||||
if( m_bAutoScroll == true )
|
||||
*pVal = VARIANT_TRUE;
|
||||
|
||||
else if( m_bAutoScroll == false )
|
||||
*pVal = VARIANT_FALSE;
|
||||
|
||||
else
|
||||
return E_FAIL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::put_AutoScroll(VARIANT_BOOL newVal)
|
||||
{
|
||||
if( newVal == VARIANT_TRUE )
|
||||
m_bAutoScroll = true;
|
||||
|
||||
else if( newVal == VARIANT_FALSE )
|
||||
m_bAutoScroll = false;
|
||||
|
||||
else
|
||||
return E_FAIL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::get_ScrollPosition(long *pVal)
|
||||
{
|
||||
tagPOINT tpOffset;
|
||||
tagSIZE tsSize;
|
||||
m_pScroller->get_Offset( &tpOffset );
|
||||
m_pScroller->get_Increments( &tsSize );
|
||||
|
||||
*pVal = tpOffset.y;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::put_ScrollPosition(long newVal)
|
||||
{
|
||||
tagPOINT tpOffset;
|
||||
tagSIZE tsSize;
|
||||
m_pScroller->get_Offset( &tpOffset );
|
||||
m_pScroller->get_Increments( &tsSize );
|
||||
|
||||
tpOffset.y = newVal;
|
||||
|
||||
m_pScroller->ScrollTo( &tpOffset );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cList::JumpToPosition(long newVal)
|
||||
{
|
||||
_ASSERTE( newVal >= 0 );
|
||||
_ASSERTE( newVal < m_rows.size() );
|
||||
|
||||
tagPOINT tpOffset;
|
||||
m_pScroller->get_Offset( &tpOffset );
|
||||
|
||||
tpOffset.y = newVal;
|
||||
|
||||
m_pScroller->put_Offset( &tpOffset );
|
||||
m_pScroller->ScrollTo( &tpOffset ); // ensures the thumb gets updated
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue