// Network.cpp : implementation file // #include "stdafx.h" #include "CityLoop.h" #include "Network.h" #ifdef _DEBUG #define new DEBUG_NEW #endif CLock theLock; CNetwork* theNetwork=NULL; // CNetwork dialog IMPLEMENT_DYNAMIC(CNetwork, CDialog) CNetwork::CNetwork(CWnd* pParent /*=NULL*/) : CDialog(CNetwork::IDD, pParent) { theNetwork = this; NetEvents = new HANDLE[EVENT_COUNT]; NetEvents[RUN_EVENT] = CreateEvent( NULL, true, false, _T("Run")); NetEvents[TERMINATE_EVENT] = CreateEvent( NULL, true, false, _T("Quit")); m_PointCount = 0; Speed = 1; bRunning = false; m_rect.SetRectEmpty(); } void CNetwork::SetSpeed(int n) { if(n >= 1 && n <= 10) { theLock.Lock(); Speed = n; theLock.Unlock(); InvalidateRect(NULL,TRUE); UpdateWindow(); } } int CNetwork::GetSpeed() { theLock.Lock(); int s = 110 - (Speed * 10); theLock.Unlock(); return s; } CNetwork::~CNetwork() { if(NetEvents) { ResetEvent(NetEvents[RUN_EVENT]); SetEvent(NetEvents[TERMINATE_EVENT]); CloseHandle(NetEvents[0]); CloseHandle(NetEvents[1]); delete[] NetEvents; NetEvents = NULL; } for(size_t o = 0; o < Objects.size(); o++) { delete Objects[o]; } Objects.clear(); } BOOL CNetwork::Create(int offset, CWnd* parent) { m_offset = offset; return CDialog::Create(IDD,parent); } void CNetwork::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CNetwork, CDialog) ON_WM_PAINT() ON_WM_WINDOWPOSCHANGED() END_MESSAGE_MAP() // CNetwork message handlers void CNetwork::Resize() { if(IsWindow(m_hWnd)) { if(GetParent()) { CRect rc; GetParent()->GetClientRect(rc); rc.bottom -= m_offset; SetWindowPos(NULL,0,0,rc.Width(),rc.Height(),SWP_NOOWNERZORDER|SWP_NOMOVE); } } } BOOL CNetwork::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here theNetwork = this; return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CNetwork::OnPaint() { try { ////////////// theLock.Lock(); ////////////// CPaintDC dc(this); // device context for painting dc.BeginPath(); CBrush b(RGB(255,255,255)); dc.FillRect(m_rect,&b); dc.SetDCPenColor(0); dc.SetBkMode(TRANSPARENT); CPoint pt(20,20); dc.RoundRect(m_rc_track,pt); dc.EndPath(); if(Resized) { Resized = false; CalcPoints(&dc); } dc.StrokePath(); dc.SetDCPenColor(RGB(0,0,0)); CBrush fill(RGB(255,155,66)); dc.SelectObject(&fill); CPoint spt; CFont fo; fo.CreatePointFont(90,_T("Arial"),&dc); dc.SelectObject(&fo); for(size_t s = 0; s < Stations.size(); s++) { spt = Stations[s]->Position; dc.Ellipse( spt.x - 6, spt.y - 6, spt.x + 6, spt.y + 6); int x = spt.x; CSize sx = dc.GetTextExtent(Stations[s]->Name); if(x + sx.cx > m_rect.Width()) x = spt.x - (sx.cx + 10); else x = spt.x + 10; dc.TextOut( x, spt.y - 20, Stations[s]->Name); } CBrush blue(RGB(65,155,255)); CBrush red(RGB(255,50,55)); CFont fn; fn.CreatePointFont(60,_T("Arial"),&dc); dc.SelectObject(&fn); for(size_t t = 0; t < Trains.size(); t++) { CTrain*& T = Trains[t]; if(GetPoint(T->GetLocation(),spt)) { if( !T->AtStation()) dc.SelectObject(&blue); else dc.SelectObject(&red); dc.Ellipse( spt.x - 6, spt.y - 6, spt.x + 6, spt.y + 6); TCHAR num[2]; num[0] = TCHAR(T->Number + 48); num[1] = 0; dc.TextOut( spt.x-3, spt.y-5, num); } } theLock.Unlock(); } catch(...) { theLock.Unlock(); } ValidateRect(NULL); } void CNetwork::CalcPoints(CPaintDC* pdc) { RailPoints.clear(); int num = pdc->GetPath(Points,PointTypes,100); if(num < 2) return; int w = m_rect.Width() / 100; if(w < 1) w = 2; RailPoints.push_back(Points[0]); for(int n = 1; n <= num; n++) { CPoint ps; CPoint pe; if(n == num) { pe = Points[0]; ps = Points[n-1]; } else { ps = Points[n-1]; pe = Points[n]; } while(pe != ps) { if(pe.y < ps.y) { ps.y -= w; if(ps.y < pe.y) ps.y = pe.y; } else if(pe.y > ps.y) { ps.y += w; if(ps.y > pe.y) ps.y = pe.y; } if(pe.x < ps.x) { ps.x -= w; if(ps.x < pe.x) ps.x = pe.x; } else if(pe.x > ps.x) { ps.x += w; if(ps.x > pe.x) ps.x = pe.x; } RailPoints.push_back(ps); } } size_t interval = RailPoints.size() / (Stations.size()+2); size_t pos = interval; for(size_t s = 0; s < Stations.size(); s++) { Stations[s]->SetPosition( RailPoints[pos], pos); pos += interval; } } void CNetwork::OnWindowPosChanged(WINDOWPOS* lp) { CRect rc(lp->x, lp->y, lp->cx-lp->x, lp->cy-lp->y); if(!m_rect.EqualRect(rc)) { Resized = true; m_rect = rc; m_rc_track = m_rect; m_rc_track.DeflateRect(35,35); Invalidate(); } CDialog::OnWindowPosChanged(lp); } size_t CNetwork::Add(TObject* o) { Objects.push_back(o); if(o->Type == TypeIsStation) Stations.push_back((CStation*)o); if(o->Type == TypeIsTrain) Trains.push_back((CTrain*)o); return Objects.size(); } void CNetwork::Start() { bRunning=true; SetEvent(NetEvents[RUN_EVENT]); ResetEvent(NetEvents[TERMINATE_EVENT]); for(size_t t = 0; t < Trains.size(); t++) { CTrain*& T = Trains[t]; T->Create(); } Resized = true; Invalidate(); } void CNetwork::Go() { if(bRunning) { SetEvent(NetEvents[RUN_EVENT]); return; } Start(); } void CNetwork::Stop() { if(bRunning) { ResetEvent(NetEvents[RUN_EVENT]); } } void CNetwork::Terminate() { SetEvent(NetEvents[TERMINATE_EVENT]); SetEvent(NetEvents[RUN_EVENT]); } BOOL CNetwork::IsRunning() { return WaitForSingleObject(NetEvents[RUN_EVENT],0) == WAIT_OBJECT_0; } BOOL CNetwork::GetPoint(size_t Loc, CPoint & pt) { if(Loc >= 0 && Loc < RailPoints.size()) { pt = RailPoints[Loc]; return true; } return false; } CStation* CNetwork::GetStation(size_t loc) { for(size_t t = 0; t < Stations.size(); t++) { if(Stations[t]->Location == loc) return Stations[t]; } return NULL; } LRESULT CNetwork::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if(message == WM_SUBWAY) { if(!IsRunning()) return 1; CRect rc; std::vector::iterator nex = Trains.begin(); while(nex != Trains.end()) { if((*nex)->Ident == wParam) { CPoint pt; size_t a = (*nex)->GetLocation(); size_t b = a > 0 ? a - 1 : 0; if(GetPoint(a,pt)) { CRgn rg; if(rg.CreateRectRgn( pt.x - 16, pt.y - 16, pt.x + 16, pt.y + 16)) { InvalidateRgn(&rg); } } if(GetPoint(b,pt)) { CRgn rg; if(rg.CreateRectRgn( pt.x - 16, pt.y - 16, pt.x + 16, pt.y + 16)) { InvalidateRgn(&rg); } } break; } nex++; } UpdateWindow(); GetParent()->SendMessage(WM_SUBWAY,wParam,0); return 1; } return CDialog::WindowProc(message, wParam, lParam); } CStation* CNetwork::GetNextStation(CStation* S) { size_t n = 0; while(n < Stations.size()) { if(Stations[n]==S) break; n++; } n++; if(n >= Stations.size()) n = 0; return Stations[n]; } DWORD CNetwork::TimeAtStation(CStation*S) { return 2000; }