void CMainDlg::OnStateChanged(EngineState::State state) { // , GUI CSyncChannel, // // Pending , , // GetDlgItem(IDC_BUTTON_START).EnableWindow(FALSE); GetDlgItem(IDC_BUTTON_STOP).EnableWindow(FALSE); GetDlgItem(IDC_BUTTON_PAUSE).EnableWindow(FALSE); GetDlgItem(IDC_BUTTON_CONTINUE).EnableWindow(FALSE); switch (state) { case EngineState::NotStarted: GetDlgItem(IDC_BUTTON_START).EnableWindow(TRUE); break; case EngineState::Started: GetDlgItem(IDC_BUTTON_STOP).EnableWindow(TRUE); GetDlgItem(IDC_BUTTON_PAUSE).EnableWindow(TRUE); break; case EngineState::Paused: GetDlgItem(IDC_BUTTON_STOP).EnableWindow(TRUE); GetDlgItem(IDC_BUTTON_CONTINUE).EnableWindow(TRUE); break; } }
//Engine.h namespace EngineState { enum State { NotStarted, StartPending, Started, PausePending, Paused, ResumePending, StopPending }; }; class IEngineEvents { public: virtual void OnStateChanged(EngineState::State state) = 0; }; class CEngine { public: CEngine(IEngineEvents* listener); ~CEngine(void); public: // void Start(); void Stop(); void Pause(); void Resume(); public: // GUI bool ProcessMessage(MSG& msg); private: void WaitForThread(); static DWORD WINAPI ThreadProc(LPVOID param); void Run(); bool CheckStopAndPause(); void ChangeState(EngineState::State state); void OnStateChanged(EngineState::State state); private: CSyncChannel m_syncChannel; // IEngineEvents* m_listener; HANDLE m_hThread; volatile EngineState::State m_state; };
// Engine.cpp CEngine::CEngine(IEngineEvents* listener) : m_listener(listener), m_hThread(NULL), m_state(EngineState::NotStarted) { m_syncChannel.Create(GetCurrentThreadId()); } CEngine::~CEngine(void) { // , m_state = EngineState::StopPending; // , . // GUI, . // , , // m_syncChannel, . m_syncChannel.Close(); // . WaitForThread(); } void CEngine::WaitForThread() { if (m_hThread) { // . // : // StopPending NotStarted _ASSERT(m_state == EngineState::StopPending || m_state == EngineState::NotStarted); // DWORD waitResult = WaitForSingleObject(m_hThread, INFINITE); _ASSERT(waitResult == WAIT_OBJECT_0); // , HANDLE CloseHandle(m_hThread); m_hThread = NULL; } } void CEngine::Start() { // , GUI // , // if (m_state == EngineState::NotStarted) { // Start , , // // , WaitForThread(); // , // this, Run m_hThread = CreateThread(NULL, 0, CEngine::ThreadProc, this, 0, NULL); if (m_hThread) { // StartPending // ChangeState(EngineState::Started) // , SyncChannel, // , // , "Start" // StartPending , // Started ChangeState(EngineState::StartPending); } } } void CEngine::Stop() { // , GUI if (m_state != EngineState::NotStarted && m_state != EngineState::StopPending) { // , ChangeState(EngineState::StopPending); } // , // // ChangeState(EngineState::Stopped) // WaitForThread } void CEngine::Pause() { // , GUI if (m_state == EngineState::Started) { // PausePending Started ChangeState(EngineState::PausePending); } } void CEngine::Resume() { // , GUI if (m_state == EngineState::Paused) { // ResumePending Paused ChangeState(EngineState::ResumePending); } } bool CEngine::ProcessMessage(MSG& msg) { // GUI return m_syncChannel.ProcessMessage(msg); } DWORD WINAPI CEngine::ThreadProc(LPVOID param) { // , // Run reinterpret_cast<CEngine*>(param)->Run(); return 0; } void CEngine::Run() { // GUI , ChangeState(EngineState::Started); for (;;) { // , - // if (!CheckStopAndPause()) { break; } // - , :) Sleep(1000); } // , ChangeState(EngineState::NotStarted); // NotStarted // - // WaitForSingleObject } bool CEngine::CheckStopAndPause() { // . // GUI. if (m_state == EngineState::StopPending) { // Stop, return false; } if (m_state == EngineState::PausePending) { // , // GUI // ChangeState(EngineState::Paused); while (m_state == EngineState::Paused) { Sleep(100); } if (m_state == EngineState::StopPending) { // Stop, return false; } // // GUI ChangeState(EngineState::Started); } // return true; } void CEngine::ChangeState(EngineState::State state) { // , // GUI , m_syncChannel m_syncChannel.Execute(boost::bind(&CEngine::OnStateChanged, this, state)); } void CEngine::OnStateChanged(EngineState::State state) { // GUI , m_state // m_state // , // GUI m_state = state; m_listener->OnStateChanged(m_state); }
class CMessageFilter { public: virtual BOOL PreTranslateMessage(MSG* pMsg) = 0; };
Source: https://habr.com/ru/post/141783/
All Articles