MFC用户界面多线程实例1

本程序基于 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 ========================

线程启动会自动调用 InitInstance() 函数, 线程退出会自动调用 ExitInstance() 函数。在类对象析构前,会调用 Delete() 函数。 MFC 内部实现,无需用户操心。

在重载这几个函数,可以自己添加代码。

函数 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;

关于 m_pDC

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: 在此处添加消息处理程序代码
}





你可能感兴趣的:(多线程,mfc,界面)