You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
4.3 KiB
C++

// 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 <Chart/XTPChartLegendItem.h>
#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
}