// XTPChartDrawThread.cpp // // This file is a part of the XTREME TOOLKIT PRO MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Common/XTPImageManager.h" #include "Common/XTPSystemHelpers.h" #include "../Types/XTPChartTypes.h" #include "../XTPChartElement.h" #include #include "../XTPChartContent.h" #include "../XTPChartControl.h" #include "XTPChartDeviceCommand.h" #include "XTPChartDeviceContext.h" #include "XTPChartDrawThread.h" ////////////////////////////////////////////////////////////////////////// // CXTPChartDrawThreadDeviceCommand CXTPChartDrawThreadDeviceCommand::CXTPChartDrawThreadDeviceCommand(CXTPChartDeviceCommand* pCommand) { AddChildCommand(pCommand); m_dwRef = 1; } CXTPChartDrawThreadDeviceCommand::~CXTPChartDrawThreadDeviceCommand() { } void CXTPChartDrawThreadDeviceCommand::AddRef() { InterlockedIncrement(&m_dwRef); } void CXTPChartDrawThreadDeviceCommand::Release() { if (m_dwRef == 0) return; LONG lResult = InterlockedDecrement(&m_dwRef); if (lResult == 0) { delete this; } } ////////////////////////////////////////////////////////////////////////// // CXTPChartDrawThread IMPLEMENT_DYNCREATE(CXTPChartDrawThread, CWinThread) CXTPChartDrawThread::CXTPChartDrawThread() { m_pCommand = NULL; m_pControl = NULL; m_szImage = CSize(0, 0); m_bImageReady = FALSE; ::InitializeCriticalSection(&m_cs); m_dwMonitorEvents[0] = CreateEvent(NULL, TRUE, FALSE, 0); // Path was changed event. m_dwMonitorEvents[1] = CreateEvent(NULL, TRUE, FALSE, 0); // Stop notifications event. } CXTPChartDrawThread::~CXTPChartDrawThread() { CloseHandle(m_dwMonitorEvents[0]); CloseHandle(m_dwMonitorEvents[1]); SAFE_RELEASE(m_pCommand); ::DeleteCriticalSection(&m_cs); } void CXTPChartDrawThread::StopNotifications() { SetEvent(m_dwMonitorEvents[1]); WaitForSingleObject(m_hThread, INFINITE); } void CXTPChartDrawThread::StartDraw(CSize sz, CXTPChartDrawThreadDeviceCommand* pCommand) { CXTPLockGuard lock(m_cs); ASSERT(pCommand); m_bImageReady = FALSE; m_szImage = sz; SAFE_RELEASE(m_pCommand); m_pCommand = pCommand; m_pCommand->AddRef(); SetEvent(m_dwMonitorEvents[0]); } BOOL CXTPChartDrawThread::MonitorNotifications() { BOOL bContinueThread = TRUE; BOOL bConinueNotifications = TRUE; while (bConinueNotifications) { // Wait for notification. DWORD dwWaitStatus = ::WaitForMultipleObjects(_countof(m_dwMonitorEvents), m_dwMonitorEvents, FALSE, INFINITE); switch (dwWaitStatus) { case WAIT_OBJECT_0: ::ResetEvent(m_dwMonitorEvents[0]); DrawContent(); break; case WAIT_OBJECT_0 + 1: bContinueThread = FALSE; bConinueNotifications = FALSE; break; } } return bContinueThread; } BOOL CXTPChartDrawThread::InitInstance() { return TRUE; } int CXTPChartDrawThread::Run() { BOOL bContinueThread = TRUE; while (bContinueThread) { bContinueThread = MonitorNotifications(); } return 0; } void CXTPChartDrawThread::DrawContent() { CXTPLockGuard lock(m_cs); CXTPChartDrawThreadDeviceCommand* pCommand = m_pCommand; m_pCommand = NULL; lock.UnLockThread(); CDC memDC; memDC.CreateCompatibleDC(NULL); m_bmpCache.DeleteObject(); m_bmpCache.Attach(CXTPImageManager::Create32BPPDIBSection(0, m_szImage.cx, m_szImage.cy, 0)); CBitmap* pOldBitmap = memDC.SelectObject(&m_bmpCache); { CXTPChartDeviceContext* pDC = m_pControl->GetContent()->CreateDeviceContext(m_pControl, memDC, CRect(0, 0, m_szImage.cx, m_szImage.cy), FALSE); pDC->Execute(pCommand); delete pDC; } memDC.SelectObject(pOldBitmap); lock.LockThread(); pCommand->Release(); if (m_pCommand == NULL) { m_bImageReady = TRUE; if (m_pControl->GetSafeHwnd()) m_pControl->Invalidate(FALSE); } // Unlocked in destructor }