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>
372 lines
7.1 KiB
C++
372 lines
7.1 KiB
C++
// Static.cpp : Implementation of cStatic
|
|
#include "stdafx.h"
|
|
#include "DecalControls.h"
|
|
#include "Static.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// cStatic
|
|
|
|
|
|
STDMETHODIMP cStatic::get_Font(IFontCacheDisp **pVal)
|
|
{
|
|
_ASSERTE( pVal != NULL );
|
|
|
|
if( m_pFont.p == NULL )
|
|
*pVal = NULL;
|
|
else
|
|
m_pFont->QueryInterface( pVal );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::putref_Font(IFontCacheDisp *newVal)
|
|
{
|
|
_ASSERTE( newVal != NULL );
|
|
|
|
if( m_pFont.p )
|
|
m_pFont.Release();
|
|
|
|
HRESULT hRes = newVal->QueryInterface( &m_pFont );
|
|
|
|
_ASSERTE( SUCCEEDED( hRes ) );
|
|
m_pSite->Invalidate();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::get_Text(BSTR *pVal)
|
|
{
|
|
_ASSERTE( pVal != NULL );
|
|
|
|
*pVal = OLE2BSTR( m_strText );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::put_Text(BSTR newVal)
|
|
{
|
|
_ASSERTE( newVal != NULL );
|
|
|
|
m_strText = newVal;
|
|
m_pSite->Invalidate();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::SchemaLoad(IView *pView, IUnknown *pSchema)
|
|
{
|
|
CComPtr< IPluginSite > pPlugin;
|
|
m_pSite->get_PluginSite( &pPlugin );
|
|
|
|
pPlugin->CreateFontSchema( 14, 0, pSchema, &m_pFont );
|
|
|
|
MSXML::IXMLDOMElementPtr pElement = pSchema;
|
|
|
|
_variant_t vText = pElement->getAttribute( _T( "text" ) ),
|
|
vTextColor = pElement->getAttribute( _T( "textcolor" ) ),
|
|
vWidth = pElement->getAttribute( _T( "width" ) ),
|
|
vHeight = pElement->getAttribute( _T( "height" ) ),
|
|
vJustify = pElement->getAttribute( _T( "justify" ) ),
|
|
vOutline = pElement->getAttribute( _T( "outlinecolor" ) ),
|
|
vAntialias = pElement->getAttribute( _T( "aa" ) );
|
|
|
|
// This is a required element
|
|
_ASSERTE( vText.vt == VT_BSTR );
|
|
|
|
// Store the text, assume left justification
|
|
m_strText = vText.bstrVal;
|
|
m_eJustify = eFontLeft;
|
|
|
|
// Determine the proper justification
|
|
if (vJustify.vt != VT_NULL)
|
|
{
|
|
_bstr_t bstrJustify = vJustify.bstrVal;
|
|
if (::_wcsicmp(L"left", bstrJustify) == 0)
|
|
{
|
|
m_eJustify = eFontLeft;
|
|
}
|
|
else if (::_wcsicmp(L"right", bstrJustify) == 0)
|
|
{
|
|
m_eJustify = eFontRight;
|
|
}
|
|
else if (::_wcsicmp(L"center", bstrJustify) == 0)
|
|
{
|
|
m_eJustify = eFontCenter;
|
|
}
|
|
}
|
|
|
|
// Determine the color
|
|
if( vTextColor.vt != VT_NULL )
|
|
{
|
|
try
|
|
{
|
|
m_nTextColor = static_cast< long >( vTextColor );
|
|
}
|
|
catch( ... )
|
|
{
|
|
// Type conversion error
|
|
_ASSERTE( FALSE );
|
|
}
|
|
}
|
|
|
|
m_nOutlineColor = 0;
|
|
m_bOutline = false;
|
|
if( vOutline.vt != VT_NULL )
|
|
{
|
|
try
|
|
{
|
|
m_bOutline = true;
|
|
m_nOutlineColor = static_cast< long >( vOutline );
|
|
}
|
|
catch( ... )
|
|
{
|
|
// Type conversion error
|
|
_ASSERTE( FALSE );
|
|
}
|
|
}
|
|
|
|
m_bAA = true;
|
|
if( vAntialias.vt != VT_NULL )
|
|
{
|
|
try
|
|
{
|
|
m_bAA = static_cast< bool >( vAntialias );
|
|
}
|
|
catch( ... )
|
|
{
|
|
// Type conversion error
|
|
_ASSERTE( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
// Set the width of the static (not same as text width)
|
|
if( vWidth.vt != VT_NULL )
|
|
{
|
|
try
|
|
{
|
|
m_nWidth = static_cast< long >( vWidth );
|
|
}
|
|
catch( ... )
|
|
{
|
|
// Type conversion error
|
|
_ASSERTE( FALSE );
|
|
}
|
|
}
|
|
|
|
// Set the height of the static (not same as text height or fontsize)
|
|
if( vHeight.vt != VT_NULL )
|
|
{
|
|
try
|
|
{
|
|
m_nHeight = static_cast< long >( vHeight );
|
|
}
|
|
catch( ... )
|
|
{
|
|
// Type conversion error
|
|
_ASSERTE( FALSE );
|
|
}
|
|
}
|
|
*/
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::Render( ICanvas *pCanvas )
|
|
{
|
|
if( m_pFont.p == NULL )
|
|
{
|
|
// Create the default font
|
|
CComPtr< IPluginSite > pPlugin;
|
|
m_pSite->get_PluginSite( &pPlugin );
|
|
|
|
BSTR bstrFontName;
|
|
pPlugin->get_FontName(&bstrFontName);
|
|
pPlugin->CreateFont( bstrFontName /*_bstr_t( _T( "Times New Roman" ) )*/, 14, 0, &m_pFont );
|
|
}
|
|
|
|
SIZE Size;
|
|
char *token;
|
|
POINT ptText = { 0, 0 };
|
|
|
|
//_bstr_t strText= m_strText.copy();
|
|
//_bstr_t temp=_bstr_t("");
|
|
|
|
// Determine control size
|
|
RECT rcPos;
|
|
m_pSite->get_Position(&rcPos);
|
|
int nWidth = rcPos.right - rcPos.left;
|
|
int nHeight = rcPos.bottom - rcPos.top;
|
|
|
|
// Copy the string for parsing
|
|
std::string strText((const char *) m_strText);
|
|
|
|
// Determine line height
|
|
m_pFont->MeasureText(_bstr_t(strText.data()), &Size);
|
|
int height = Size.cy;
|
|
|
|
// Break it into lines (can't use strtok or we miss blank lines)
|
|
std::vector<_bstr_t> lines;
|
|
int nStart = 0, nEnd;
|
|
bool bDone = false;
|
|
while (!bDone)
|
|
{
|
|
// Get the next CR
|
|
nEnd = strText.find("\n", nStart);
|
|
if (nEnd == std::string::npos)
|
|
{
|
|
bDone = true;
|
|
nEnd = strText.length();
|
|
}
|
|
|
|
// Store the line
|
|
lines.push_back(strText.substr(nStart, nEnd - nStart).data());
|
|
|
|
// Move one character beyond
|
|
nStart = nEnd + 1;
|
|
}
|
|
|
|
// Loop through the lines
|
|
_bstr_t bstrSpace(" "), bstrEmpty("");
|
|
int nIndex, nLines = lines.size();
|
|
for (nIndex = 0, bDone = false; !bDone && (nIndex < nLines); nIndex++)
|
|
{
|
|
// Copy the line for parsing
|
|
_bstr_t strLine((const char *) lines[nIndex]);
|
|
|
|
// Line to be built
|
|
_bstr_t strOut = bstrEmpty;
|
|
|
|
// Loop through the "words" on the line
|
|
for (token = ::strtok((char *) strLine, " "); !bDone && (token != NULL); token = ::strtok(NULL, " "))
|
|
{
|
|
_bstr_t bstrToken(token);
|
|
|
|
// Measure this token
|
|
m_pFont->MeasureText(strOut + bstrToken, &Size);
|
|
|
|
// Is this line full???
|
|
if (Size.cx > nWidth)
|
|
{
|
|
DrawText(&ptText, strOut, pCanvas);
|
|
ptText.y += height;
|
|
|
|
// Does the next line put us over the top
|
|
bDone = ((ptText.y + height) > nHeight) ? true : false;
|
|
|
|
// Clear the line
|
|
strOut = bstrEmpty;
|
|
}
|
|
|
|
// Store the token
|
|
strOut += bstrToken + bstrSpace;
|
|
}
|
|
|
|
// Draw as needed
|
|
if (!bDone)
|
|
{
|
|
DrawText(&ptText, strOut, pCanvas);
|
|
ptText.y += height;
|
|
}
|
|
|
|
// Does the next line put us over the top
|
|
bDone = ((ptText.y + height) > nHeight) ? true : false;
|
|
}
|
|
|
|
/*
|
|
if(Size.cx > nWidth)
|
|
{
|
|
for( token = ::strtok( (char*)strText, " " ); token !=NULL; token = ::strtok( NULL, " " ) )
|
|
{
|
|
m_pFont->MeasureText(temp + _bstr_t(token), &Size);
|
|
|
|
if(Size.cx > nWidth)
|
|
{
|
|
DrawText( &ptText, temp, pCanvas );
|
|
ptText.y+=height;//14;
|
|
if(ptText.y+height>nHeight)
|
|
return S_OK;
|
|
temp = _bstr_t(token) + _bstr_t(" ");
|
|
}
|
|
else
|
|
temp += _bstr_t(token) + _bstr_t(" ");
|
|
}
|
|
|
|
DrawText( &ptText, temp, pCanvas );
|
|
|
|
}
|
|
else
|
|
{
|
|
DrawText( &ptText, strText, pCanvas );
|
|
}
|
|
*/
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::get_TextColor(long *pVal)
|
|
{
|
|
_ASSERTE( pVal != NULL );
|
|
|
|
*pVal = m_nTextColor;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP cStatic::put_TextColor(long newVal)
|
|
{
|
|
_ASSERTE( ( newVal & 0xFF000000L ) == 0 );
|
|
|
|
m_nTextColor = newVal;
|
|
m_pSite->Invalidate();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void cStatic::DrawText(LPPOINT ppt, BSTR szText, ICanvas *pCanvas)
|
|
{
|
|
POINT pt = *ppt;
|
|
|
|
RECT rcPos;
|
|
m_pSite->get_Position(&rcPos);
|
|
int nWidth = rcPos.right - rcPos.left;
|
|
int nHeight = rcPos.bottom - rcPos.top;
|
|
|
|
// Act based on justification style
|
|
switch (m_eJustify)
|
|
{
|
|
case eFontRight:
|
|
{
|
|
SIZE Size;
|
|
m_pFont->MeasureText(szText, &Size);
|
|
pt.x = nWidth - Size.cx;
|
|
}
|
|
break;
|
|
|
|
case eFontCenter:
|
|
{
|
|
SIZE Size;
|
|
m_pFont->MeasureText(szText, &Size);
|
|
pt.x = (nWidth / 2) - (Size.cx / 2);
|
|
}
|
|
break;
|
|
|
|
case eFontLeft:
|
|
default:
|
|
{
|
|
// No-Op
|
|
}
|
|
break;
|
|
}
|
|
|
|
long lFlags = 0;
|
|
|
|
if( m_bAA )
|
|
lFlags |= eAA;
|
|
|
|
if( m_bOutline )
|
|
lFlags |= eOutlined;
|
|
|
|
m_pFont->DrawTextEx( &pt, szText, m_nTextColor, m_nOutlineColor, lFlags, pCanvas );
|
|
}
|