本程序基于 VS2008,参考 MFC demo 做的。
写该文章的作用给自己做个备份,以后好直接用自己写好的代码。随便发表出来,赚点人气。
工程中新建一个基于 CWinThread 的类 CGift .
CGift 内部需要一个变量记录其对象个数,以及何时初始化临界区,销毁临界区。
还有一个临界区变量。
屏蔽 MFC 界面线程采用的消息循环,采用事件机制运行和结束线程。
头文件部分代码如下:
class CGift : public CWinThread { DECLARE_DYNAMIC(CGift) protected: // CGift(); // 动态创建所使用的受保护的构造函数 virtual ~CGift(); CGift(CWnd* pWnd, HDC hDC); public: virtual BOOL InitInstance(); virtual int ExitInstance(); void Delete(); public: void KillThread(); void UpdateBorder(); virtual void SingleStep() = 0; public: HANDLE m_hEventKill; HANDLE m_hEventDead; CRect m_rectBorder; HDC m_hDC; CDC* m_pDC; protected: static CRITICAL_SECTION m_csGiftLock; private: static int m_nCounter; //记录类对象个数 public: inline int GetThreadCount(){return m_nCounter;} protected: DECLARE_MESSAGE_MAP() };
//=========== Class CGift Area ================= CRITICAL_SECTION CGift::m_csGiftLock; int CGift::m_nCounter = 0; // CGift //IMPLEMENT_DYNCREATE(CGift, CWinThread) IMPLEMENT_DYNAMIC(CGift, CWinThread) CGift::CGift(CWnd* pWnd, HDC hDC) { m_bAutoDelete = FALSE; // 线程不随着类对象的消亡而终止 m_pMainWnd = pWnd; m_pMainWnd->GetClientRect(&m_rectBorder); m_hDC = hDC; m_pDC = new CDC; m_nCounter++; m_hEventKill = CreateEvent(NULL, TRUE, FALSE, NULL); m_hEventDead = CreateEvent(NULL, TRUE, FALSE, NULL); } CGift::~CGift() { m_nCounter--; delete m_pDC; CloseHandle(m_hEventDead); CloseHandle(m_hEventKill); } BOOL CGift::InitInstance() { // TODO: 在此执行任意逐线程初始化 m_pDC->Attach(m_hDC); if (m_nCounter == 1) { InitializeCriticalSection(&CGift::m_csGiftLock); } while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT) { SingleStep(); } return FALSE; // 不进入消息循环 //return TRUE; } void CGift::Delete() { CWinThread::Delete(); SetEvent(m_hEventDead); } int CGift::ExitInstance() { // TODO: 在此执行任意逐线程清理 if (m_nCounter == 1) { DeleteCriticalSection(&CGift::m_csGiftLock); } m_pDC->Detach(); return CWinThread::ExitInstance(); } void CGift::KillThread() { SetEvent(m_hEventKill); SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL); WaitForSingleObject(m_hEventDead, INFINITE); WaitForSingleObject(m_hThread, INFINITE); delete this; } void CGift::UpdateBorder() { EnterCriticalSection(&CGift::m_csGiftLock); { m_pMainWnd->GetClientRect(&m_rectBorder); } LeaveCriticalSection(&CGift::m_csGiftLock); } BEGIN_MESSAGE_MAP(CGift, CWinThread) END_MESSAGE_MAP() // CGift 消息处理程序 //========= end ========================
在重载这几个函数,可以自己添加代码。
函数 SingleStep() 是线程要完成的事。由继承类做。
关于 IMPLEMENT_DYNCREATE 和 IMPLEMENT_DYNAMIC , 可以视情况而定。
接下来在新建一个继承 CGift 的 类 CFire , 该类为用户 DIY 类,自己设定其功能,调用该类。
头文件部分代码:
class CFire : public CGift { DECLARE_DYNAMIC(CFire) #define RECTANGLE_LENGTH 200 // 矩形长 #define RECTANGLE_WIDTH 200 // 矩形宽 public: CFire(CWnd* pWnd, HDC hDC, CRect rectangle); CFire(CWnd* pWnd, HDC hDC, CPoint centrePoint); ~CFire(); public: virtual BOOL InitInstance(); virtual BOOL ExitInstance(); virtual void SingleStep(); CRect m_rectangle; CPoint m_point; CBrush m_brush; char m_flag; };
//======== Class CFire Area =========== IMPLEMENT_DYNAMIC(CFire, CGift) CFire::CFire(CWnd* pWnd, HDC hDC, CRect rectangle) : CGift(pWnd, hDC) { m_rectangle = rectangle; } CFire::CFire(CWnd* pWnd, HDC hDC, CPoint centrePoint) : CGift(pWnd, hDC) { m_rectangle.SetRect(centrePoint.x - RECTANGLE_LENGTH/2, centrePoint.y - RECTANGLE_WIDTH/2, centrePoint.x + RECTANGLE_LENGTH/2, centrePoint.y + RECTANGLE_WIDTH/2); m_point.x = centrePoint.x; m_point.y = m_rectangle.bottom; } CFire::~CFire() { } BOOL CFire::InitInstance() { return CGift::InitInstance(); } BOOL CFire::ExitInstance() { CBrush brush(RGB(0,0,0)); EnterCriticalSection(&CGift::m_csGiftLock); { m_pDC->FillRect(m_rectangle,&brush); // m_pDC->FillSolidRect(m_rectangle, m_dc.GetBkColor()); GdiFlush(); } LeaveCriticalSection(&CGift::m_csGiftLock); return CGift::ExitInstance(); } void CFire::SingleStep() { if (m_point.y-- < m_rectangle.top) { m_point.y = m_rectangle.bottom; } EnterCriticalSection(&CGift::m_csGiftLock); { for (int i = -10; i < 11; i++) { m_pDC->SetPixelV(m_point.x + i, m_point.y, RGB(121,37,69)); } if ((m_rectangle.bottom - m_point.y) > 10) { for (int i = -10; i < 11; i++) { m_pDC->SetPixelV(m_point.x + i, m_point.y+10, RGB(0,0,0)); } } GdiFlush(); } LeaveCriticalSection(&CGift::m_csGiftLock); Sleep(10); } //======== end ====================
调用类创建线程如下:
m_pThread = new CFire(this, m_pDC->GetSafeHdc(), point); m_pThread->CreateThread(CREATE_SUSPENDED); m_pThread->SetThreadPriority(THREAD_PRIORITY_IDLE); m_pThread->ResumeThread(); m_threadList.AddTail(m_pThread);
相关变量声明部分:
CTypedPtrList<CObList, CGift*> m_threadList; CClientDC* m_pDC; CGift* m_pThread;
int CBirthdayGiftView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您专用的创建代码 m_pDC = new CClientDC(this); return 0; }
void CBirthdayGiftView::OnKillthreads() { while (!m_threadList.IsEmpty()) { m_threadList.RemoveHead()->KillThread(); } }
void CBirthdayGiftView::OnDestroy() { OnKillthreads(); CView::OnDestroy(); // TODO: 在此处添加消息处理程序代码 }