www.pudn.com > ParticleTest.rar > ParticleTestView.cpp


// ParticleTestView.cpp : implementation of the CParticleTestView class 
// 
 
#include "stdafx.h" 
#include "ParticleTest.h" 
 
#include "ParticleTestDoc.h" 
#include "ParticleTestView.h" 
 
 
#include  
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CParticleTestView 
 
IMPLEMENT_DYNCREATE(CParticleTestView, CView) 
 
BEGIN_MESSAGE_MAP(CParticleTestView, CView) 
	//{{AFX_MSG_MAP(CParticleTestView) 
	ON_WM_ERASEBKGND() 
	ON_WM_TIMER() 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_MM_TEXT, OnUpdateMapmodeMmText) 
	ON_COMMAND(ID_MAPMODE_MM_TEXT, OnMapmodeMmText) 
	ON_COMMAND(ID_MAPMODE_LOENGLISH, OnMapmodeLoenglish) 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_LOENGLISH, OnUpdateMapmodeLoenglish) 
	ON_COMMAND(ID_MAPMODE_MMHIGHENGLISH, OnMapmodeMmhighenglish) 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_MMHIGHENGLISH, OnUpdateMapmodeMmhighenglish) 
	ON_COMMAND(ID_FLICKER_OFF, OnFlickerOff) 
	ON_UPDATE_COMMAND_UI(ID_FLICKER_OFF, OnUpdateFlickerOff) 
	ON_COMMAND(ID_FLICKER_ON, OnFlickerOn) 
	ON_UPDATE_COMMAND_UI(ID_FLICKER_ON, OnUpdateFlickerOn) 
	ON_COMMAND(ID_MAPMODE_HIMETRIC, OnMapmodeHimetric) 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_HIMETRIC, OnUpdateMapmodeHimetric) 
	ON_COMMAND(ID_MAPMODE_LOMETRIC, OnMapmodeLometric) 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_LOMETRIC, OnUpdateMapmodeLometric) 
	ON_COMMAND(ID_MAPMODE_TWIPS, OnMapmodeTwips) 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_TWIPS, OnUpdateMapmodeTwips) 
	ON_COMMAND(ID_MAPMODE_ANISOTRIPIC, OnMapmodeAnisotripic) 
	ON_UPDATE_COMMAND_UI(ID_MAPMODE_ANISOTRIPIC, OnUpdateMapmodeAnisotripic) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CParticleTestView construction/destruction 
 
CParticleTestView::CParticleTestView() 
{ 
	m_mapmode = MM_TEXT; 
	m_flickerFlag = FALSE; 
} 
 
CParticleTestView::~CParticleTestView() 
{ 
	m_container.Clean(); 
} 
 
BOOL CParticleTestView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
 
	return CView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CParticleTestView drawing 
 
CString MapMode(long mapmode) 
{ 
	switch (mapmode) { 
	case MM_TEXT: return _T("MM_TEXT"); 
	case MM_TWIPS: return _T("MM_TWIPS"); 
	case MM_LOENGLISH: return _T("MM_LOENGLISH"); 
	case MM_HIENGLISH: return _T("MM_HIENGLISH"); 
	case MM_LOMETRIC: return _T("MM_LOMETRIC"); 
	case MM_HIMETRIC: return _T("MM_HIMETRIC"); 
	case MM_ANISOTROPIC: return _T("MM_ANISOTROPIC"); 
	} 
	return _T("???"); 
} 
 
void CParticleTestView::OnDraw(CDC* dc) 
{ 
	CRect bounds; 
	CRect lBounds; 
	GetClientRect(&bounds); 
	lBounds = bounds; 
 
	if (m_flickerFlag) { 
		dc->DPtoLP(&lBounds); 
		dc->FillSolidRect(lBounds, dc->GetBkColor()); 
		m_container.Draw(dc, bounds); 
		dc->SetTextColor(RGB(255, 255, 255)); 
		dc->SetBkMode(TRANSPARENT); 
		dc->SetTextAlign(TA_LEFT | TA_TOP); 
		dc->TextOut(0, 0, MapMode(dc->GetMapMode())); 
	} else { 
		CMemDC pDC(dc); 
		m_container.Draw(pDC, bounds); 
		pDC->SetTextColor(RGB(255, 255, 255)); 
		pDC->SetBkMode(TRANSPARENT); 
		pDC->SetTextAlign(TA_LEFT | TA_TOP); 
		pDC->TextOut(0, 0, MapMode(pDC->GetMapMode())); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CParticleTestView diagnostics 
 
#ifdef _DEBUG 
void CParticleTestView::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
 
void CParticleTestView::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
CParticleTestDoc* CParticleTestView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CParticleTestDoc))); 
	return (CParticleTestDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CParticleTestView message handlers 
 
BOOL CParticleTestView::OnEraseBkgnd(CDC* pDC)  
{ 
	if (m_flickerFlag) { 
		return CView::OnEraseBkgnd(pDC); 
	} 
	return FALSE; 
} 
 
void CParticleTestView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)  
{ 
	pDC->SetBkColor(RGB(0, 0, 0)); 
	pDC->SetMapMode(m_mapmode); 
	CView::OnPrepareDC(pDC, pInfo); 
} 
 
void CParticleTestView::OnTimer(UINT nIDEvent)  
{ 
	if (nIDEvent == 1) { 
		CRect client; 
		GetClientRect(&client); 
		m_container.Update(client); 
		Invalidate(); 
	} 
} 
 
void CParticleTestView::OnInitialUpdate()  
{ 
	CRect client; 
	CView::OnInitialUpdate(); 
 
	srand( (unsigned)time( NULL ) ); 
	 
	SetTimer(1, 33, NULL); 
 
	GetClientRect(&client); 
 
	m_container.Clean(); 
 
	m_container.Add(new CParentParticle( 
					CPoint(client.left+client.Width()/2, client.top+client.Height()/2),  
					CPoint(2, -3),  
					RGB(255, 0, 0))); 
 
	m_container.Add(new CParentParticle( 
					CPoint(client.left+client.Width()/2, client.top+client.Height()/2),  
					CPoint(rand()%3, rand()%7-3),  
					RGB(0, 255, 0))); 
 
	m_container.Add(new CParentParticle( 
					CPoint(client.left+client.Width()/2, client.top+client.Height()/2),  
					CPoint(rand()%3, rand()%7-3),  
					RGB(100, 100, 255))); 
 
	m_container.Add(new CParentParticle( 
					CPoint(client.left+client.Width()/2, client.top+client.Height()/2),  
					CPoint(rand()%3, rand()%7-3),  
					RGB(250, 200, 255))); 
 
	m_container.Add(new CParentParticle( 
					CPoint(client.left+client.Width()/2, client.top+client.Height()/2),  
					CPoint(rand()%3, rand()%7-3),  
					RGB(243, 236, 288))); 
 
	m_container.Add(new CParentParticle( 
					CPoint(client.left+client.Width()/2, client.top+client.Height()/2),  
					CPoint(rand()%3, rand()%7-3),  
					RGB(255, 255, 255))); 
} 
 
 
int CParticleContainer::GetSize() const {return m_array.GetSize();} 
CParticle* CParticleContainer::GetAt(int index) {return m_array.GetAt(index);} 
void CParticleContainer::RemoveAt(int index) {m_array.RemoveAt(index);} 
void CParticleContainer::Add(CParticle* value) {m_array.Add(value);} 
void CParticleContainer::Clean() 
{ 
	for (int i = GetSize()-1; i >= 0; i--) { 
		if (GetAt(i) != NULL) delete GetAt(i); 
		RemoveAt(i); 
	} 
} 
void CParticleContainer::Update(const CRect& bounds)  
{ 
	CParticleContainer container; 
	int size = GetSize(); 
 
	for (int i = 0; i < size; i++) { 
		CParticle* pParticle = GetAt(i); 
		if (pParticle != NULL && pParticle->UpdateTick(bounds, NULL, container)) { 
			RemoveAt(i); 
			delete pParticle; 
			size = GetSize(); 
			continue; 
		} 
	} 
 
	size = container.GetSize(); 
 
	for (i = 0; i < size; i++) { 
		Add(container.GetAt(i)); 
	} 
} 
 
void CParticleContainer::Draw(CDC* pDC, const CRect& bounds)  
{ 
	for (int i = 0; i < GetSize(); i++) { 
		CParticle* pParticle = GetAt(i); 
		if (pParticle != NULL) pParticle->Draw(pDC, bounds); 
	} 
} 
 
 
CParentParticle::CParentParticle(CPoint loc, CPoint velocity, COLORREF color) : CParticle(loc, velocity, color) 
{ 
	m_pen = new CPen(PS_SOLID, 1, color); 
	m_updateTick = 0; 
} 
CParentParticle::~CParentParticle()  
{ 
	if (m_pen != NULL) delete m_pen; 
} 
 
double Random() 
{ 
	static double sum = 0.0; 
	static double count = 0.0; 
 
	double retval = ((double) rand())/((double) RAND_MAX)-0.5; 
	sum += retval; 
	count += 1.0; 
	return retval; 
} 
 
BOOL CParentParticle::UpdateTick(const CRect& bounds, CParticle* parent, CParticleContainer& decayList)  
{ 
	CPoint prev = m_loc; 
 
	m_loc.x += m_velocity.x; 
	m_loc.y += m_velocity.y; 
 
	if (m_loc.x >= bounds.right) { 
		m_loc.x = m_loc.x - bounds.right; 
	} 
 
	if (m_loc.x < bounds.left) { 
		m_loc.x = bounds.right - (m_loc.x - bounds.left); 
	} 
 
	if (m_loc.y >= bounds.bottom) { 
		m_loc.y = m_loc.y - bounds.bottom; 
	} 
 
	if (m_loc.y < bounds.top) { 
		m_loc.y = bounds.bottom - (m_loc.y - bounds.top); 
	} 
 
	m_updateTick++; 
 
	if (m_updateTick % 10 == 0) { 
		m_velocity.x += (long) (5.0*Random()); 
		m_velocity.y += (long) (5.0*Random()); 
		if (m_velocity.x > 4) m_velocity.x = 4; 
		if (m_velocity.x < -4) m_velocity.x = -4; 
		if (m_velocity.y > 4) m_velocity.y = 4; 
		if (m_velocity.y < -4) m_velocity.y = -4; 
	} 
 
	for (int i = 0; i < rand()%3; i++) { 
		decayList.Add(new CChildParticle(m_loc, CPoint(0, 0), m_color)); 
	} 
 
	return FALSE; 
} 
 
BOOL CParentParticle::Draw(CDC* pDC, const CRect& bounds)  
{ 
	CPoint lpPoint = m_loc; 
 
	pDC->DPtoLP(&lpPoint); 
	CPen* pOldPen = pDC->SelectObject(m_pen); 
	pDC->MoveTo(lpPoint); 
	lpPoint = CPoint(m_loc.x+m_velocity.x, m_loc.y+m_velocity.y); 
	pDC->DPtoLP(&lpPoint); 
	pDC->LineTo(lpPoint); 
	pDC->SelectObject(pOldPen); 
	return TRUE; 
} 
 
 
CChildParticle::CChildParticle(CPoint loc, CPoint velocity, COLORREF color) : CParticle(loc, velocity, color) 
{ 
	m_updateTick = 0; 
	m_drawColor = color; 
} 
 
CChildParticle::~CChildParticle() {} 
 
BOOL CChildParticle::UpdateTick(const CRect& bounds, CParticle* parent, CParticleContainer& decayList)  
{ 
	const long decay = 400; 
	const long colorDecay = 275; 
	 
	m_updateTick++; 
 
	m_drawColor = RGB(GetRValue(m_color)*(colorDecay-m_updateTick)/colorDecay, 
						GetGValue(m_color)*(colorDecay-m_updateTick)/colorDecay, 
						GetBValue(m_color)*(colorDecay-m_updateTick)/colorDecay); 
 
	m_loc.x += (long) (Random()*2.5); 
	m_loc.y += (m_loc.y + 600)/decay; 
 
	return !bounds.PtInRect(m_loc) || m_drawColor == RGB(0, 0, 0); 
} 
 
BOOL CChildParticle::Draw(CDC* pDC, const CRect& bounds)  
{ 
	CPoint lpPoint; 
	CPen pen(PS_SOLID, 1, m_drawColor); 
	CPen* pOldPen = pDC->SelectObject(&pen); 
	lpPoint = m_loc; 
	pDC->DPtoLP(&lpPoint); 
	pDC->MoveTo(lpPoint); 
	lpPoint = CPoint(m_loc.x+m_velocity.x+1, m_loc.y+m_velocity.y+1); 
	pDC->DPtoLP(&lpPoint); 
	pDC->LineTo(lpPoint); 
	pDC->SelectObject(pOldPen); 
	return TRUE; 
} 
 
BOOL CParticleTestView::DestroyWindow()  
{ 
	KillTimer(1); 
	return CView::DestroyWindow(); 
} 
 
void CParticleTestView::OnUpdateMapmodeMmText(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_TEXT); 
} 
 
void CParticleTestView::OnMapmodeMmText()  
{ 
	m_mapmode = MM_TEXT; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom); 
} 
 
void CParticleTestView::OnMapmodeLoenglish()  
{ 
	m_mapmode = MM_LOENGLISH; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom); 
} 
 
void CParticleTestView::OnUpdateMapmodeLoenglish(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_LOENGLISH); 
} 
 
void CParticleTestView::OnMapmodeMmhighenglish()  
{ 
	m_mapmode = MM_HIENGLISH; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom); 
} 
 
void CParticleTestView::OnUpdateMapmodeMmhighenglish(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_HIENGLISH); 
} 
 
void CParticleTestView::OnFlickerOff()  
{ 
	m_flickerFlag = FALSE; 
	 
} 
 
void CParticleTestView::OnUpdateFlickerOff(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(!m_flickerFlag); 
} 
 
void CParticleTestView::OnFlickerOn()  
{ 
	m_flickerFlag = TRUE; 
} 
 
void CParticleTestView::OnUpdateFlickerOn(CCmdUI* pCmdUI)  
{ 
	pCmdUI->SetCheck(m_flickerFlag); 
} 
 
void CParticleTestView::OnMapmodeHimetric()  
{ 
	m_mapmode = MM_HIMETRIC; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom); 
} 
 
void CParticleTestView::OnUpdateMapmodeHimetric(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_HIMETRIC); 
} 
 
void CParticleTestView::OnMapmodeLometric()  
{ 
	m_mapmode = MM_LOMETRIC; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom); 
	 
} 
 
void CParticleTestView::OnUpdateMapmodeLometric(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_LOMETRIC); 
} 
 
void CParticleTestView::OnMapmodeTwips()  
{ 
	m_mapmode = MM_TWIPS; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom);	 
} 
 
void CParticleTestView::OnUpdateMapmodeTwips(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_TWIPS); 
} 
 
void CParticleTestView::OnMapmodeAnisotripic()  
{ 
	m_mapmode = MM_ANISOTROPIC; 
 
	CRect client; 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	GetClientRect(&client); 
	dc.DPtoLP(&client); 
	Invalidate(); 
	TRACE("%s - bounds (%d, %d, %d, %d)\n", MapMode(dc.GetMapMode()), client.left, client.top, client.right, client.bottom);		 
} 
 
void CParticleTestView::OnUpdateMapmodeAnisotripic(CCmdUI* pCmdUI)  
{ 
	CClientDC dc(this); 
	OnPrepareDC(&dc); 
	pCmdUI->SetCheck(dc.GetMapMode() == MM_ANISOTROPIC); 
}