/** * @file XTPGaugeBaseType.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "Common/Base/Diagnostic/XTPDisableAdvancedWarnings.h" #include #include "Common/Base/Diagnostic/XTPEnableAdvancedWarnings.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPMarkupRender.h" #include "Common/XTPResourceManager.h" #include "Common/XTPActiveScriptEngine.h" #include "Common/XTPVC80Helpers.h" #include "Common/Base/Types/XTPSize.h" #include "GraphicLibrary/GdiPlus/XTPGdiPlus.h" #include #include "Markup/XTPMarkupObject.h" #include "Markup/XTPMarkupContext.h" #include "Markup/XTPMarkupDrawingContext.h" #include "Markup/XTPMarkupInputElement.h" #include "Markup/XTPMarkupUIElement.h" #include "Gauge/Resource.h" #include "Gauge/XTPGaugeBaseType.h" #include "Gauge/XTPGaugeCtrl.h" #include "Gauge/XTPGaugeTraits.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # undef THIS_FILE static char THIS_FILE[] = __FILE__; # define new DEBUG_NEW #endif #ifndef E_BOUNDS # define E_BOUNDS _HRESULT_TYPEDEF_(0x8000000BL) #endif /////////////////////////////////////////////////////////////////////////////// // JPath helpers static HRESULT JPathExtractName(LPCWSTR& pPath, LPWSTR& pName) { _ASSERTE(NULL != pPath); LPCWSTR p = wcschr(pPath, L'.'); if (NULL == p) { pName = _wcsdup(pPath); pPath = NULL; return S_OK; } size_t len = static_cast(p - pPath); size_t cb = (len + 1) * 2; pName = reinterpret_cast(malloc(cb)); if (NULL == pName) return E_OUTOFMEMORY; memcpy(pName, pPath, cb); pName[len] = L'\0'; pPath += len + 1; if (L'\0' == *pPath) pPath = NULL; return S_OK; } static HRESULT JPathExtractIndex(LPWSTR pName, LONG& nIndex) { _ASSERTE(NULL != pName); LPCWSTR p1 = wcschr(pName, L'['); if (NULL == p1) return S_FALSE; LPCWSTR p2 = wcschr(p1 + 1, L']'); if (NULL == p2) return E_INVALIDARG; LPCWSTR p = p1 + 1; while (p < p2) { if (!isdigit(*p++)) return E_INVALIDARG; } nIndex = _wtol(p1 + 1); pName[p1 - pName] = L'\0'; return S_OK; } static HRESULT JPathGet(LPDISPATCH pDisp, LPCWSTR pName, COleVariant& vtValue) { _ASSERTE(NULL != pDisp); _ASSERTE(NULL != pName); LPOLESTR rNames[] = { const_cast(pName) }; DISPID dispid = 0; HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, rNames, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (S_OK != hr) return hr; vtValue.Clear(); DISPPARAMS dp = { 0 }; hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, &vtValue, NULL, NULL); return hr; } static HRESULT JPathSet(LPDISPATCH pDisp, LPCWSTR pName, const COleVariant& vtValue) { _ASSERTE(NULL != pDisp); _ASSERTE(NULL != pName); LPOLESTR rNames[] = { const_cast(pName) }; DISPID dispid = 0; HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, rNames, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (S_OK != hr) return hr; DISPID dispidNamed = DISPID_PROPERTYPUT; DISPPARAMS dp = { 0 }; dp.rgvarg = const_cast(&vtValue); dp.cArgs = 1; dp.rgdispidNamedArgs = &dispidNamed; dp.cNamedArgs = 1; hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, NULL, NULL, NULL); return hr; } static HRESULT JPathExecute(LPDISPATCH pDisp, LPCWSTR pPath, COleVariant* pvtGetValue = NULL, const COleVariant* pvtSetValue = NULL) { _ASSERTE(NULL != pDisp); _ASSERTE(NULL != pPath); _ASSERTE(pvtGetValue != pvtSetValue); HRESULT hr = E_UNEXPECTED; LPWSTR pName = NULL; pDisp->AddRef(); while (TRUE) { if (NULL != pName) { free(pName); pName = NULL; } hr = JPathExtractName(pPath, pName); if (S_OK != hr) break; LONG nIndex = 0; hr = JPathExtractIndex(pName, nIndex); BOOL bIndexed = (S_OK == hr); if (FAILED(hr)) break; if (bIndexed) { COleVariant vtObject; hr = JPathGet(pDisp, pName, vtObject); if (S_OK != hr) break; if (VT_DISPATCH != vtObject.vt) { hr = E_INVALIDARG; break; } COleVariant vtLength; hr = JPathGet(vtObject.pdispVal, L"length", vtLength); if (S_OK != hr) break; if (VT_I4 != vtLength.vt) { hr = E_INVALIDARG; break; } if (vtLength.lVal <= nIndex) { hr = E_BOUNDS; break; } WCHAR szIndex[10]; ITOW_S(nIndex, szIndex, _countof(szIndex), 10); if (NULL == pPath) { if (NULL != pvtSetValue) { hr = JPathSet(vtObject.pdispVal, szIndex, *pvtSetValue); if (S_OK != hr) break; } if (NULL != pvtGetValue) { hr = JPathGet(vtObject.pdispVal, szIndex, *pvtGetValue); if (S_OK != hr) break; } hr = S_OK; break; } COleVariant vtNext; hr = JPathGet(vtObject.pdispVal, szIndex, vtNext); if (S_OK != hr) break; if (VT_DISPATCH != vtNext.vt) { hr = E_INVALIDARG; break; } pDisp->Release(); pDisp = vtNext.Detach().pdispVal; } else { if (NULL == pPath) { if (NULL != pvtSetValue) { hr = JPathSet(pDisp, pName, *pvtSetValue); if (S_OK != hr) break; } if (NULL != pvtGetValue) { hr = JPathGet(pDisp, pName, *pvtGetValue); if (S_OK != hr) break; } hr = S_OK; break; } COleVariant vtNext; hr = JPathGet(pDisp, pName, vtNext); if (S_OK != hr) break; if (VT_DISPATCH != vtNext.vt) { hr = E_INVALIDARG; break; } pDisp->Release(); pDisp = vtNext.Detach().pdispVal; } } if (NULL != pName) free(pName); pDisp->Release(); return hr; } /////////////////////////////////////////////////////////////////////////////// // CXTPGaugeBaseType IMPLEMENT_DYNAMIC(CXTPGaugeBaseType, CXTPCmdTarget); const CXTPGaugeBaseType::JSLib CXTPGaugeBaseType::m_JSLibs[] = { { L"runtime", XTP_GAUGE_RESOURCE_RUNTIMELIB }, { L"sprintf", XTP_GAUGE_RESOURCE_SPRINTFLIB }, { L"gauge", XTP_GAUGE_RESOURCE_GAUGELIB }, { L"json2", XTP_GAUGE_RESOURCE_JSON2LIB }, { L"easing", XTP_GAUGE_RESOURCE_EASINGLIB } }; CXTPGaugeBaseType::CXTPGaugeBaseType() : m_pCtrl(NULL) , m_bAutomaticUpdate(FALSE) , m_pUserTraits(NULL) , m_pMarkupContext(NULL) , m_pMarkupRoot(NULL) , m_pInitObj(NULL) , m_pDispTraits(NULL) , m_pDispUpdate(NULL) , m_pDispShutdown(NULL) , m_pDispInput(NULL) , m_pDispDumpTraits(NULL) , m_bDirty(FALSE) { EnableAutomation(); } CXTPGaugeBaseType::~CXTPGaugeBaseType() { _ASSERTE(NULL == m_pDispDumpTraits); _ASSERTE(NULL == m_pDispInput); _ASSERTE(NULL == m_pDispShutdown); _ASSERTE(NULL == m_pDispUpdate); _ASSERTE(NULL == m_pDispTraits); _ASSERTE(NULL == m_pInitObj); _ASSERTE(NULL == m_pMarkupRoot); _ASSERTE(NULL == m_pMarkupContext); } BOOL CXTPGaugeBaseType::Load(CXTPMarkupContext* pContext, IStream& stream, const CXTPGaugeTraits& traits) { _ASSERTE(NULL != pContext); Unload(); m_pMarkupContext = pContext; m_pUserTraits = &traits; LPDISPATCH pDispGauge = GetIDispatch(FALSE); pContext->AddCustomScriptItem(L"Gauge", pDispGauge); m_pMarkupContext->SetClientSite(this); m_pMarkupRoot = XTPMarkupParseText(pContext, &stream); if (NULL == m_pMarkupRoot) { Unload(); TRACE(_T("Unable to load gauge source from the specified source\n")); return FALSE; } OnLoad(); m_pUserTraits = NULL; return TRUE; } void CXTPGaugeBaseType::Unload() { if (NULL != m_pMarkupContext) OnCleanup(); SAFE_RELEASE(m_pDispDumpTraits); SAFE_RELEASE(m_pDispInput); SAFE_RELEASE(m_pDispShutdown); SAFE_RELEASE(m_pDispUpdate); SAFE_RELEASE(m_pDispTraits); SAFE_RELEASE(m_pInitObj); if (NULL != m_pMarkupContext) { m_pMarkupContext->RemoveCustomScriptItem(L"Gauge"); m_pMarkupContext = NULL; MARKUP_RELEASE(m_pMarkupRoot); } } void CXTPGaugeBaseType::Draw(CDC& dc, CRect rc) { if (NULL == m_pMarkupRoot) return; XTPMarkupRenderElement(m_pMarkupRoot, dc, rc); } void CXTPGaugeBaseType::TraceTraits() const { #ifdef _DEBUG CString strTraits; if (!DumpTraits(strTraits)) strTraits = _T(""); strTraits += _T("\n"); OutputDebugString(strTraits); #endif } HRESULT CXTPGaugeBaseType::GetTrait(LPCTSTR pJPath, COleVariant& vtValue) const { _ASSERTE(NULL != m_pDispTraits); if (NULL == m_pDispTraits) return E_POINTER; return const_cast(this)->GetDispValue(m_pDispTraits, XTP_CT2CW(pJPath), vtValue); } HRESULT CXTPGaugeBaseType::SetTrait(LPCTSTR pJPath, const COleVariant& vtValue) { _ASSERTE(NULL != m_pDispTraits); if (NULL == m_pDispTraits) return E_POINTER; HRESULT hr = SetDispValue(m_pDispTraits, XTP_CT2CW(pJPath), vtValue); if (SUCCEEDED(hr)) SetDirty(); return hr; } HRESULT CXTPGaugeBaseType::Update() { _ASSERTE(NULL != m_pDispUpdate); if (NULL == m_pDispUpdate) return E_POINTER; if (!m_bDirty) return S_FALSE; CXTPActiveScriptObjectContext* pCtx = GetMarkupContext()->GetScriptEngine()->CreateContext( m_pDispUpdate); HRESULT hr = pCtx->Invoke(); pCtx->Release(); if (SUCCEEDED(hr)) m_bDirty = FALSE; return hr; } BOOL CXTPGaugeBaseType::DumpTraits(CString& strTraits) const { if (NULL == m_pDispDumpTraits) return FALSE; CXTPActiveScriptObjectContext* pCtx = const_cast(this)->GetMarkupContext()->GetScriptEngine()->CreateContext( m_pDispDumpTraits); COleVariant vtResult; HRESULT hr = pCtx->Invoke((VARIANT*)&vtResult); pCtx->Release(); if (FAILED(hr)) return FALSE; vtResult.ChangeType(VT_BSTR); if (NULL == vtResult.bstrVal) return FALSE; strTraits = XTP_CW2CT(vtResult.bstrVal); return TRUE; } HRESULT CXTPGaugeBaseType::InvokeAction(LPCTSTR lpName, const COleVariant& vtArg /*= COleVariant()*/, COleVariant* pvtResult /*= NULL*/) { _ASSERTE(NULL != lpName); CString strJPath = _T("actions."); strJPath += lpName; COleVariant vtAction; HRESULT hr = GetDispValue(m_pDispTraits, XTP_CT2CW(strJPath), vtAction); if (FAILED(hr)) return hr; // TODO: Named actions can be cached in future if (VT_DISPATCH != vtAction.vt) return E_NOINTERFACE; CXTPActiveScriptObjectContext* pCtx = GetMarkupContext()->GetScriptEngine()->CreateContext( vtAction.pdispVal); VARIANT args[2]; args[0].vt = VT_DISPATCH; args[0].pdispVal = GetIDispatch(FALSE); args[1] = vtArg; hr = pCtx->InvokeWithArgs(args, _countof(args), pvtResult); pCtx->Release(); return hr; } void CXTPGaugeBaseType::OnLoad() { InvokeAction(_T("init")); } void CXTPGaugeBaseType::OnInit() { } void CXTPGaugeBaseType::OnUpdate() { } void CXTPGaugeBaseType::OnCleanup() { if (NULL == m_pDispShutdown) return; CXTPActiveScriptObjectContext* pCtx = GetMarkupContext()->GetScriptEngine()->CreateContext( m_pDispShutdown); pCtx->Invoke(); pCtx->Release(); } void CXTPGaugeBaseType::SetDirty() { m_bDirty = TRUE; } HRESULT CXTPGaugeBaseType::GetDispValue(LPDISPATCH pDisp, LPCWSTR pJPath, COleVariant& vtValue) const { return JPathExecute(pDisp, pJPath, &vtValue); } HRESULT CXTPGaugeBaseType::SetDispValue(LPDISPATCH pDisp, LPCWSTR pJPath, const COleVariant& vtValue) { return JPathExecute(pDisp, pJPath, NULL, &vtValue); } void CXTPGaugeBaseType::GetNamedObject(LPDISPATCH pDisp, LPCWSTR pJPath, VARTYPE vt, BOOL bRequired, COleVariant& vtValue) const { _ASSERTE(NULL != pDisp); _ASSERTE(NULL != pJPath); HRESULT hr = GetDispValue(pDisp, pJPath, vtValue); if (FAILED(hr)) { if (bRequired) { CString msg; msg.Format(_T("Unable to get value of '%s'"), pJPath); TRACE(_T("%s\n"), msg.operator LPCTSTR()); AfxThrowOleDispatchException(static_cast(GetScode(hr) & 0xffff), msg); } return; } BOOL bNull = (VT_BSTR == vtValue.vt || VT_DISPATCH == vtValue.vt || VT_UNKNOWN == vtValue.vt || VT_SAFEARRAY == vtValue.vt || 0 != (vtValue.vt & VT_ARRAY) ? NULL == vtValue.byref : FALSE); if (bRequired && (vt != vtValue.vt || bNull)) { CString msg; msg.Format(_T("Invalid '%s' value or value type"), pJPath); TRACE(_T("%s\n"), msg.operator LPCTSTR()); AfxThrowOleDispatchException(static_cast(GetScode(hr) & 0xffff), msg); } } void CXTPGaugeBaseType::Bind(CXTPGaugeCtrl* pCtrl) { _ASSERTE(NULL == m_pCtrl); _ASSERTE(NULL != pCtrl); m_pCtrl = pCtrl; } BOOL CXTPGaugeBaseType::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT& lResult) { if (NULL == m_pMarkupRoot) return FALSE; if (NULL != m_pDispInput && ((WM_KEYDOWN == message || WM_KEYUP == message || WM_CHAR == message) || (WM_MOUSEFIRST <= message && message <= WM_MOUSELAST))) { CXTPActiveScriptObjectContext* pCtx = GetMarkupContext()->GetScriptEngine()->CreateContext( m_pDispInput); VARIANT args[3]; args[0].vt = VT_I4; args[0].lVal = static_cast(message); args[1].vt = VT_I4; args[1].lVal = static_cast(wParam); args[2].vt = VT_I4; args[2].lVal = static_cast(lParam); COleVariant vtResult; pCtx->InvokeWithArgs(args, _countof(args), &vtResult); pCtx->Release(); if (VT_EMPTY != vtResult.vt && VT_NULL != vtResult.vt) { if (VT_I1 == vtResult.vt || VT_I2 == vtResult.vt || VT_I4 == vtResult.vt || VT_I8 == vtResult.vt || VT_UI1 == vtResult.vt || VT_UI2 == vtResult.vt || VT_UI4 == vtResult.vt || VT_UI8 == vtResult.vt || VT_UINT == vtResult.vt || VT_INT == vtResult.vt || VT_R4 == vtResult.vt || VT_R8 == vtResult.vt) { vtResult.ChangeType(VT_I4); lResult = vtResult.lVal; } else { TRACE(_T("Unable to convert returned type %i to LRESULT\n"), vtResult.vt); lResult = 0; } return TRUE; } } return XTPMarkupRelayMessage(m_pMarkupRoot, message, wParam, lParam, &lResult); } CString CXTPGaugeBaseType::GetJSLib(UINT nResourceID) const { HMODULE hResource = XTPResourceManager()->GetResourceHandle(); if (NULL == hResource) hResource = XTPGetInstanceHandle(); CComPtr pStream; HRESULT hr = XTPCreateReadOnlyResourceStream(hResource, MAKEINTRESOURCE(nResourceID), _T("JS"), FALSE, &pStream); if (FAILED(hr)) { TRACE(_T("Unable to load JavaScript library (resId=%i) [hr=0x%08X]\n"), nResourceID, hr); return _T(""); } STATSTG st; if (FAILED(pStream->Stat(&st, STATFLAG_NONAME))) return _T(""); if (0 != st.cbSize.HighPart || 0 == st.cbSize.LowPart) return _T(""); CArray buffer; buffer.SetSize(XTPToIntPtr(st.cbSize.LowPart)); ULONG cb = 0; if (FAILED(pStream->Read(buffer.GetData(), st.cbSize.LowPart, &cb))) return _T(""); buffer.SetSize(XTPToIntPtrChecked(cb + 1)); buffer.SetAt(XTPToIntPtrChecked(cb), '\0'); return XTP_CA2CT(buffer.GetData()); } LPWSTR CXTPGaugeBaseType::PrepareCodeChunk(LPCWSTR pCode, const CList& requirements) { _ASSERTE(NULL != pCode); if (requirements.IsEmpty()) return NULL; CString strCode; static const WCHAR libPrefix[] = L"lib:"; POSITION pos = requirements.GetHeadPosition(); while (NULL != pos) { LPCWSTR pReq = requirements.GetNext(pos); _ASSERTE(NULL != pReq); if (0 != wcsncmp(pReq, libPrefix, _countof(libPrefix) - 1)) continue; LPCWSTR pLibName = pReq + _countof(libPrefix) - 1; for (int i = 0; i < _countof(m_JSLibs); ++i) { if (0 == wcscmp(pLibName, m_JSLibs[i].pName)) { TRACE(_T("Linking JavaScript library: %ls (resId=%u)\n"), pLibName, m_JSLibs[i].nResID); strCode += L"\n\n//======== lib:"; strCode += pLibName; strCode += L" ========\n\n"; strCode += GetJSLib(m_JSLibs[i].nResID); break; } } } if (strCode.IsEmpty()) return NULL; strCode += L"\n\n//======== Script source code ========\n\n"; strCode += pCode; return _wcsdup(XTP_CT2CW(strCode)); } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_DISPATCH_MAP(CXTPGaugeBaseType, CXTPCmdTarget) DISP_PROPERTY_EX(CXTPGaugeBaseType, "traits", OleGetTraits, SetNotSupported, VT_DISPATCH) DISP_PROPERTY_EX(CXTPGaugeBaseType, "userTraits", OleGetUserTraits, SetNotSupported, VT_BSTR) DISP_PROPERTY_EX(CXTPGaugeBaseType, "userTraitsArg", OleGetUserTraitsArg, SetNotSupported, VT_BSTR) DISP_PROPERTY_EX(CXTPGaugeBaseType, "isDebug", OleIsDebug, SetNotSupported, VT_BOOL) DISP_FUNCTION(CXTPGaugeBaseType, "getTraitsModifiers", OleGetTraitsModifiers, VT_EMPTY, VTS_DISPATCH) DISP_FUNCTION(CXTPGaugeBaseType, "init", OleInit, VT_EMPTY, VTS_DISPATCH) DISP_FUNCTION(CXTPGaugeBaseType, "getLibrary", OleGetLibrary, VT_BSTR, VTS_WBSTR) DISP_FUNCTION(CXTPGaugeBaseType, "update", OleUpdate, VT_EMPTY, VTS_NONE) DISP_FUNCTION(CXTPGaugeBaseType, "redraw", OleRedraw, VT_EMPTY, VTS_NONE) DISP_FUNCTION(CXTPGaugeBaseType, "setTransparentBackgroundColor", OleSetTransparentBackgroundColor, VT_EMPTY, VTS_DISPATCH) DISP_FUNCTION(CXTPGaugeBaseType, "setBackgroundColor", OleSetBackgroundColor, VT_EMPTY, VTS_DISPATCH) DISP_FUNCTION(CXTPGaugeBaseType, "dpiX", OleDpiX, VT_R8, VTS_R8) DISP_FUNCTION(CXTPGaugeBaseType, "dpiY", OleDpiY, VT_R8, VTS_R8) DISP_FUNCTION(CXTPGaugeBaseType, "undpiX", OleUnDpiX, VT_R8, VTS_R8) DISP_FUNCTION(CXTPGaugeBaseType, "undpiY", OleUnDpiY, VT_R8, VTS_R8) END_DISPATCH_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" void CXTPGaugeBaseType::OleInit(LPDISPATCH pData) { // Though m_pInitObj is not used anywhere, having it ensure the object passed to 'init' is kept // alive. Not having it leads to quite strange side effects that are extremely hard to debug. m_pInitObj = pData; m_pInitObj->AddRef(); COleVariant vtTraits; GetNamedObject(pData, L"traits", VT_DISPATCH, TRUE, vtTraits); vtTraits.pdispVal->AddRef(); COleVariant vtInit; GetNamedObject(pData, L"init", VT_DISPATCH, TRUE, vtInit); COleVariant vtUpdate; GetNamedObject(pData, L"update", VT_DISPATCH, TRUE, vtUpdate); COleVariant vtShutdown; GetNamedObject(pData, L"shutdown", VT_DISPATCH, FALSE, vtShutdown); COleVariant vtTypeName; GetNamedObject(vtTraits.pdispVal, L"type", VT_BSTR, TRUE, vtTypeName); COleVariant vtInput; GetNamedObject(pData, L"input", VT_DISPATCH, FALSE, vtInput); COleVariant vtDumpTraits; GetNamedObject(pData, L"dumpTraits", VT_DISPATCH, FALSE, vtDumpTraits); if (0 != wcscmp(vtTypeName.bstrVal, GetTypeName())) { TRACE(_T("Incompatible gauge markup type, '%ls' required\n"), GetTypeName()); AfxThrowOleDispatchException(static_cast(GetScode(E_FAIL) & 0xffff), _T("Incompatible gauge markup type")); return; } m_pDispTraits = vtTraits.pdispVal; m_pDispTraits->AddRef(); m_pDispUpdate = vtUpdate.pdispVal; m_pDispUpdate->AddRef(); if (VT_DISPATCH == vtInput.vt && NULL != vtInput.pdispVal) { m_pDispInput = vtInput.pdispVal; m_pDispInput->AddRef(); } if (VT_DISPATCH == vtShutdown.vt && NULL != vtShutdown.pdispVal) { m_pDispShutdown = vtShutdown.pdispVal; m_pDispShutdown->AddRef(); } if (VT_DISPATCH == vtDumpTraits.vt && NULL != vtDumpTraits.pdispVal) { m_pDispDumpTraits = vtDumpTraits.pdispVal; m_pDispDumpTraits->AddRef(); } CXTPActiveScriptObjectContext* pCtx = GetMarkupContext()->GetScriptEngine()->CreateContext( vtInit.pdispVal); pCtx->Invoke(); pCtx->Release(); OnInit(); } LPDISPATCH CXTPGaugeBaseType::OleGetTraits() { return m_pDispTraits; } BSTR CXTPGaugeBaseType::OleGetUserTraits() { return (NULL != m_pUserTraits ? m_pUserTraits->GetTraits().AllocSysString() : ::SysAllocString(L"")); } BSTR CXTPGaugeBaseType::OleGetUserTraitsArg() { return (NULL != m_pUserTraits ? m_pUserTraits->GetCompositeTraitsArgument().AllocSysString() : ::SysAllocString(L"")); } BOOL CXTPGaugeBaseType::OleIsDebug() { #ifdef _DEBUG return TRUE; #else return FALSE; #endif } void CXTPGaugeBaseType::OleGetTraitsModifiers(LPDISPATCH pCallback) { if (NULL == m_pUserTraits || NULL == pCallback) return; POSITION pos = m_pUserTraits->EnumCustomTraits(); if (NULL == pos) return; CXTPActiveScriptObjectContext* pCtx = GetMarkupContext()->GetScriptEngine()->CreateContext( pCallback); CString strJsonPath; COleVariant* pValue = NULL; while (m_pUserTraits->GetNextCustomTrait(pos, strJsonPath, pValue)) { VARIANT args[2] = { { 0 } }; args[0].vt = VT_BSTR; args[0].bstrVal = strJsonPath.AllocSysString(); ::VariantCopy(&args[1], pValue); pCtx->InvokeWithArgs(args, _countof(args)); } pCtx->Release(); } BSTR CXTPGaugeBaseType::OleGetLibrary(LPCOLESTR pName) { for (int i = 0; i < _countof(m_JSLibs); ++i) { if (0 == wcscmp(pName, m_JSLibs[i].pName)) return GetJSLib(m_JSLibs[i].nResID).AllocSysString(); } return NULL; } void CXTPGaugeBaseType::OleUpdate() { _ASSERTE(NULL != m_pCtrl); SetDirty(); Update(); OnUpdate(); m_pCtrl->NotifyUpdate(*this); } void CXTPGaugeBaseType::OleRedraw() { _ASSERTE(NULL != m_pCtrl); m_pCtrl->RedrawWindow(); } void CXTPGaugeBaseType::OleSetTransparentBackgroundColor(LPDISPATCH pBrushDisp) { if (!XTP_ASSERT_CHECK(NULL != pBrushDisp)) return; CXTPMarkupSolidColorBrush* pBrush = MARKUP_DYNAMICCAST(CXTPMarkupSolidColorBrush, CXTPMarkupObject::FromDispatch(pBrushDisp)); if (!XTP_ASSERT_CHECK(NULL != pBrush)) { pBrushDisp->Release(); return; } COLORREF crColor = pBrush->GetColor()->GetCOLORREF(); m_pCtrl->SetTransparentBackgroundColor(crColor); pBrushDisp->Release(); } void CXTPGaugeBaseType::OleSetBackgroundColor(LPDISPATCH pBrushDisp) { if (!XTP_ASSERT_CHECK(NULL != pBrushDisp)) return; CXTPMarkupSolidColorBrush* pBrush = MARKUP_DYNAMICCAST(CXTPMarkupSolidColorBrush, CXTPMarkupObject::FromDispatch(pBrushDisp)); if (!XTP_ASSERT_CHECK(NULL != pBrush)) { pBrushDisp->Release(); return; } COLORREF crColor = pBrush->GetColor()->GetCOLORREF(); m_pCtrl->SetBackgroundColor(crColor); pBrushDisp->Release(); } double CXTPGaugeBaseType::OleDpiX(double dX) { if (NULL == m_pMarkupContext) AfxThrowOleException(E_PENDING); return m_pMarkupContext->ScaleX(dX); } double CXTPGaugeBaseType::OleDpiY(double dY) { if (NULL == m_pMarkupContext) AfxThrowOleException(E_PENDING); return m_pMarkupContext->ScaleY(dY); } double CXTPGaugeBaseType::OleUnDpiX(double dX) { if (NULL == m_pMarkupContext) AfxThrowOleException(E_PENDING); return m_pMarkupContext->UnscaleX(dX); } double CXTPGaugeBaseType::OleUnDpiY(double dY) { if (NULL == m_pMarkupContext) AfxThrowOleException(E_PENDING); return m_pMarkupContext->UnscaleY(dY); }