MFC使用List Control案例,定时刷新显示线程中发生的事件

一、前置工作
准备有如图所示的MFC界面,即开关线程的按钮以及显示数据的List Control控件(List Control控件属性中view视图必须更改为report否则不显示任何效果!)。
list control控件使用
右键list control控件添加变量m_list

二.编程目标
开启线程后,在线程中收集在整个项目其他活动的发生并放入一个队列(此处全部用开启线程活动代替其他活动)。并设置一个定时器定时刷新队列中的数据,然后显示在list control中。

三.实现
1.在初始化代码处实现以下内容:

// TODO: 在此添加额外的初始化代码
	m_LogList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_LogList.InsertColumn(m_iIndex++, _T("序号"), LVCFMT_CENTER,60);
	m_LogList.InsertColumn(m_iIndex++, _T("时间"), LVCFMT_CENTER, 260);
	m_LogList.InsertColumn(m_iIndex++, _T("日志内容"), LVCFMT_CENTER, 290);        //列

	InitializeCriticalSection(&g_cs);                //初始化临界区
	m_heventClose = CreateEvent(NULL, TRUE, FALSE, NULL);      //事件CreateEvent
	SetTimer(0, 100, NULL);              //设置定时器,100ms刷新一次。并在OnTime函数中实现和控件的交互

在.h文件实现的变量:

	int m_iIndex;            //顶部的列号,在设置列的时候用上
	HANDLE m_heventClose;      //定义事件变量

在.cpp文件实现的全局变量和结构体:

typedef struct
{
	std::string strLog;           //日志内容
	std::string strTime;		//日志时间
}TLog;

CRITICAL_SECTION g_cs;           //线程锁
std::queue<TLog> g_LogQue;		//日志队列
  1. 双击开启线程按钮,该按钮的事件函数:
ResetEvent(m_heventClose);               //重置事件,将重新开启线程
_beginthreadex(NULL, 0, ThreadFun, this, 0, NULL);  //开启线程

双击关闭线程按钮,该按钮事件函数:

SetEvent(m_heventClose);     //触发事件,则线程停止

3.开启线程之后,线程函数ThreadFun(void* pParam):

unsigned int __stdcall ThreadFun(void* pParam)
{
	CCcpp7241Dlg* pdlg = (CCcpp7241Dlg*)pParam;

	while (true)
	{
		if ( WAIT_OBJECT_0 == WaitForSingleObject(pdlg->m_heventClose, 1000) )  //当触发事件后停止线程,没有触发则线程一直运行
		{
			return 0;
		}
		
		EnterCriticalSection(&g_cs);

		TLog log;
		log.strLog = "开启线程";
		log.strTime = CT2A( CTime::GetCurrentTime().Format("%Y年%m月%d日 %X").GetString() );
		g_LogQue.push(log);

		LeaveCriticalSection(&g_cs);

	}

	EnterCriticalSection(&g_cs);

	TLog log;
	log.strLog = "关闭线程";
	log.strTime = CT2A(CTime::GetCurrentTime().Format("%Y年%m月%d日 %X").GetString());  //获取系统的当前时间
	g_LogQue.push(log);  //将获取的时间和事件日志内容放入队列中

	LeaveCriticalSection(&g_cs);
	
	return 0;
}

4.在初始化部分的代码中已经setTimer开启了定时器,在OnTimer函数中将刷新的队列展示在list control中:

void CCcpp7241Dlg::OnTimer(UINT_PTR nIDEvent)
{
	CString str;
	TLog log;

	EnterCriticalSection(&g_cs);             //由于对队列操作是不受线程保护的,所以需要加锁

	if ( g_LogQue.size() > 0 )              //判断是否队列为空,为空时不执行下列代码,即无新事件发生时不显示数据
	{
		int cnt = m_LogList.GetItemCount();         //获取当前行数
		str.Format(_T("%d"), cnt);
		m_LogList.InsertItem(cnt, str);            //设置下一行的序号
		
		log = g_LogQue.front();
		g_LogQue.pop();

		str = log.strTime.c_str();              //String类内容转换为CString
		m_LogList.SetItemText(cnt, 1, str);     //行列中设置值
		str = log.strLog.c_str();
		m_LogList.SetItemText(cnt, 2, str);     //行列中设置值
	}

	LeaveCriticalSection(&g_cs);

	CDialogEx::OnTimer(nIDEvent);
}

因为只有一个定时器使用,所以没有使用switch结构。

5.结果图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值