/** * @file XTPApplication.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/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPFramework.h" #include "Common/XTPColorManager.h" #include #include "Markup/XTPMarkupContext.h" #include "GraphicLibrary/GdiPlus/XTPGdiPlus.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef _AFXDLL // This is to enforce CXTPApplication instance to be constructed // prior to any consumer object. static const CXTPApplication* gpApplicationInstance = XTPGetApplication(); #endif /////////////////////////////////////////////////////////////////////////////// // CXTPAutoInitFlag class CXTPAutoInitFlag { public: CXTPAutoInitFlag(BOOL& bFlag, BOOL bCurrentState, BOOL bResetState, BOOL bCommittedState) : m_bFlag(bFlag) , m_bResetState(bResetState) , m_bCommittedState(bCommittedState) , m_bCommitted(FALSE) { m_bFlag = bCurrentState; } ~CXTPAutoInitFlag() { if (!m_bCommitted) m_bFlag = m_bResetState; } void Commit() { m_bFlag = m_bCommittedState; m_bCommitted = TRUE; } private: BOOL& m_bFlag; BOOL m_bResetState; BOOL m_bCommittedState; BOOL m_bCommitted; }; /////////////////////////////////////////////////////////////////////////////// // CXTPApplication IMPLEMENT_DYNAMIC(CXTPApplication, CObject); CXTPApplication::CXTPApplication() : m_pModuleState(AfxGetModuleState()) , m_bInitialized(FALSE) , m_pComInit(NULL) , m_dwThreadId(::GetCurrentThreadId()) , m_bShutdown(FALSE) , m_hGdiPlusModule(NULL) , m_nGdiplusToken(0) , m_pGdiplusStartupOutput(new Gdiplus::GdiplusStartupOutput) { } CXTPApplication::~CXTPApplication() { // It's important to call XTPShutdown, not just Shutdown. XTPShutdown(); } AFX_MODULE_STATE* CXTPApplication::GetModuleState() { return m_pModuleState; } void CXTPApplication::SetAmbientProperty(XTPApplicationAmbientProperty nProperty, COleVariant vtValue) { _ASSERTE(0 <= nProperty && nProperty < xtpApplicationPropertyCount); COleVariant& vtCurrentValue = m_arAmbientProperties[nProperty]; if (XTPVariantEqual(vtCurrentValue, vtValue)) return; vtCurrentValue = vtValue; TriggerAmbientPropertyUpdate(nProperty); } const COleVariant& CXTPApplication::GetAmbientProperty(XTPApplicationAmbientProperty nProperty) const { _ASSERTE(0 <= nProperty && nProperty < xtpApplicationPropertyCount); return m_arAmbientProperties[nProperty]; } void CXTPApplication::TriggerAmbientPropertyUpdate(XTPApplicationAmbientProperty nProperty) { Notify(&IXTPApplicationEvents::OnAmbientPropertyChanged, nProperty); } int CXTPApplication::GetComInitFlags() const { _ASSERTE(NULL != m_pComInit); return m_pComInit->GetInitFlags(); } CXTPApplication& AFX_CDECL CXTPApplication::GetInstance() { static CXTPApplication app; _ASSERTE("XTP application has been already shutdown" && !app.m_bShutdown); if (app.m_bShutdown) AfxThrowOleException(E_FAIL); return app; } BOOL CXTPApplication::Initialize(int xtpComInit) { _ASSERTE(!m_bInitialized); _ASSERTE(NULL == m_pComInit); if (m_bInitialized) { TRACE(_T("XTP has already been initialized.\n")); return TRUE; } m_pComInit = new CXTPComInitializer( xtpComInitForce | (xtpComInitAppDefault == xtpComInit ? xtpComInitAfxOle : xtpComInit)); if (FAILED(m_pComInit->GetInitializationStatus())) { TRACE(_T("COM initializer has failed. Code 0x%08X\n"), m_pComInit->GetInitializationStatus()); return FALSE; } CXTPAutoInitFlag autoInit(m_bInitialized, TRUE, FALSE, TRUE); m_hGdiPlusModule = ::LoadLibrary(_T("GdiPlus.dll")); if (NULL == m_hGdiPlusModule) { TRACE(_T("GDI+ DLL cannot be loaded, code %i.\n"), GetLastError()); return FALSE; } using namespace Gdiplus; GdiplusStartupInput gdiplusStartupInput; gdiplusStartupInput.SuppressBackgroundThread = TRUE; GdiplusStartup(&m_nGdiplusToken, &gdiplusStartupInput, m_pGdiplusStartupOutput); m_pGdiplusStartupOutput->NotificationHook(&m_nGdiplusToken); InitAmbientProperties(); CXTPMarkupContext::RegisterClasses(); autoInit.Commit(); return TRUE; } void CXTPApplication::Shutdown() { if (m_bShutdown) return; TRACE0("Codejock XTP application shutting down ...\n"); CXTPMarkupContext::UnregisterClasses(); NotifyReversed(&IXTPApplicationEvents::OnBeforeApplicationShutdown); NotifyReversed(&IXTPApplicationEvents::OnApplicationShutdown); NotifyReversed(&IXTPApplicationEvents::OnAfterApplicationShutdown); if (NULL != m_hGdiPlusModule) { using namespace Gdiplus; if (NULL != m_pGdiplusStartupOutput) m_pGdiplusStartupOutput->NotificationUnhook(m_nGdiplusToken); GdiplusShutdown(m_nGdiplusToken); FreeLibrary(m_hGdiPlusModule); m_hGdiPlusModule = NULL; } SAFE_DELETE(m_pGdiplusStartupOutput); SAFE_DELETE(m_pComInit); TRACE0("Codejock XTP application shutting down complete.\n"); m_bShutdown = TRUE; } void CXTPApplication::InitAmbientProperties() { m_arAmbientProperties[xtpApplicationAccentColor] = COleVariant(LONG(COLORREF_NULL)); m_arAmbientProperties[xtpApplicationStateColor] = COleVariant(LONG(COLORREF_NULL)); m_arAmbientProperties[xtpApplicationUseSystemAccentColor] = COleVariant(LONG(0)); } static BOOL g_bXTPInitializeStatus = FALSE; static BOOL g_bXTPInitializeAttempted = FALSE; BOOL AFX_CDECL XTPInitialize(int xtpComInit /*= xtpComInitAppDefault*/) { if (!g_bXTPInitializeAttempted) { g_bXTPInitializeAttempted = TRUE; g_bXTPInitializeStatus = XTPGetApplication()->Initialize(xtpComInit); } return g_bXTPInitializeStatus; } CXTPApplication* AFX_CDECL XTPGetApplication() { return &CXTPApplication::GetInstance(); } void AFX_CDECL XTPShutdown() { // Perform application shutting down just once. static CXTPApplication* pApp = XTPGetApplication(); if (NULL != pApp) { XTPGetApplication()->Shutdown(); pApp = NULL; #ifndef _AFXDLL gpApplicationInstance = NULL; #endif } }