Thread function programming based on MFC

When using MFC to read local video files for playback, operations such as pausing cannot be performed after starting playback, so thread operations need to be considered to implement the pause function.
The AfxBeginThread() function is used, and this array is called as the passing parameter of the thread function. Refer to [ MFC's AfxbeginThread thread creation, suspension, release, end, exit ]
Here we simply use the control of the accumulator to simulate video playback. The accumulator adds a number, which is equivalent to reading a new frame of the video. After clicking the start button, an automatically incrementing number is displayed in the "Sample Edit Box". After clicking pause, the button changes to "continue", and the thread is paused at the same time, and the number stops increasing. After clicking step again, the number increases every time step is clicked. 1. Click "continue" again to start incrementing again. Click stop to stop incrementing. At this time, clicking the step button will no longer increase.
accumulator
Add thread-related definitions in .h, which need to be defined as static

int cnt = 0;//计数器
int terminal_flag = 0;//stop标志
CWinThread *m_pThread;//线程名
static UINT jisuan(LPVOID pParam);//线程函数

The added thread function is as follows. Use this pointer to point to the counter cnt, display it in the edit control, and increase the value of cnt:

UINT CMFC_thread_2Dlg::jisuan(LPVOID lpParam)
{
    
    
	CMFC_thread_2Dlg *pDlg = (CMFC_thread_2Dlg *)lpParam;
	int i;
	CString str;
	while (TRUE) {
    
    
		i = pDlg->cnt;
		str.Format(_T("%d"), i);
		pDlg->cnt++;
		::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), str);
		Sleep(1000);
	}
	return 0;

}

The thread function is called using the AfxBeginThread() function, and the parameters are mainly the thread function name jisuan and the passed parameter this:

m_pThread = AfxBeginThread(
		jisuan,
		this,
		THREAD_PRIORITY_NORMAL,
		0,
		0,
		NULL
		);

The complete .h and .cpp files look like this:
.h file:


// MFC_thread_2Dlg.h : 头文件
//

#pragma once
#include "afxwin.h"

#define WM_UPDATE_STATIC (WM_USER + 100)  //added
// CMFC_thread_2Dlg 对话框
class CMFC_thread_2Dlg : public CDialogEx
{
    
    
// 构造
public:
	CMFC_thread_2Dlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum {
    
     IDD = IDD_MFC_THREAD_2_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
	//static UINT jisuan(LPVOID lpParam);

// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedStart();
	afx_msg void OnBnClickedDialog();
	CEdit m_text;//
	int cnt = 0;//计数器
	int terminal_flag = 0;//stop标志
	CWinThread *m_pThread;//线程名
	static UINT jisuan(LPVOID pParam);//线程函数
	
	afx_msg void OnBnClickedStop();
	afx_msg void OnBnClickedStep();
};

cpp file:


// MFC_thread_2Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "MFC_thread_2.h"
#include "MFC_thread_2Dlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框



class CAboutDlg : public CDialogEx
{
    
    
public:
	CAboutDlg();

// 对话框数据
	enum {
    
     IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
    
    
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    
    
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFC_thread_2Dlg 对话框



CMFC_thread_2Dlg::CMFC_thread_2Dlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CMFC_thread_2Dlg::IDD, pParent)
{
    
    
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFC_thread_2Dlg::DoDataExchange(CDataExchange* pDX)
{
    
    
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT1, m_text);
}

BEGIN_MESSAGE_MAP(CMFC_thread_2Dlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_START, &CMFC_thread_2Dlg::OnBnClickedStart)
	ON_BN_CLICKED(IDC_DIALOG, &CMFC_thread_2Dlg::OnBnClickedDialog)
	ON_BN_CLICKED(IDC_STOP, &CMFC_thread_2Dlg::OnBnClickedStop)
	ON_BN_CLICKED(IDC_STEP, &CMFC_thread_2Dlg::OnBnClickedStep)
END_MESSAGE_MAP()


// CMFC_thread_2Dlg 消息处理程序

BOOL CMFC_thread_2Dlg::OnInitDialog()
{
    
    
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
    
    
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
    
    
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO:  在此添加额外的初始化代码
	//m_pThread = AfxBeginThread((AFX_THREADPROC)jisuan, this);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMFC_thread_2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    
    
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
    
    
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
    
    
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMFC_thread_2Dlg::OnPaint()
{
    
    
	if (IsIconic())
	{
    
    
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
    
    
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFC_thread_2Dlg::OnQueryDragIcon()
{
    
    
	return static_cast<HCURSOR>(m_hIcon);
}

//线程函数
UINT CMFC_thread_2Dlg::jisuan(LPVOID lpParam)
{
    
    
	
	CMFC_thread_2Dlg *pDlg = (CMFC_thread_2Dlg *)lpParam;

	int i;
	
	CString str;

	while (TRUE) {
    
    
		
		i = pDlg->cnt;
		str.Format(_T("%d"), i);
		pDlg->cnt++;
		//::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), L"Hello World");
		//Sleep(1000);
		::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), str);
		Sleep(1000);
	}
	return 0;

}
//开始线程,进行累加显示
void CMFC_thread_2Dlg::OnBnClickedStart()
{
    
    
	// TODO:  在此添加控件通知处理程序代码
	
	terminal_flag = 1;
		m_pThread = AfxBeginThread(
		jisuan,
		this,
		THREAD_PRIORITY_NORMAL,
		0,
		0,
		NULL
		);
}
//暂停、继续线程
void CMFC_thread_2Dlg::OnBnClickedDialog()
{
    
    
	// TODO:  在此添加控件通知处理程序代码
	//AfxMessageBox(_T("列表为空!"));

	CString button_str0;
	button_str0 = "pause";

	CEdit *pBoxOne;
	pBoxOne = (CEdit*)GetDlgItem(IDC_DIALOG);

	CString button_str;
	pBoxOne->GetWindowText(button_str);

	
	
	if (button_str == button_str0)
	{
    
    
		m_pThread->SuspendThread();
		pBoxOne->SetWindowText(_T("continue"));
		
	}
	else
	{
    
    
		m_pThread->ResumeThread();
		pBoxOne->SetWindowText(_T("pause"));
	}

}
//停止线程
void CMFC_thread_2Dlg::OnBnClickedStop()
{
    
    
	// TODO:  在此添加控件通知处理程序代码
	TerminateThread(m_pThread->m_hThread, 0);
	terminal_flag = -1;
}
//单步增加累加器的值并显示
void CMFC_thread_2Dlg::OnBnClickedStep()
{
    
    
	// TODO:  在此添加控件通知处理程序代码
	//更改edit control 内容
	CString str_text;
	CEdit *pBoxText;
	if (terminal_flag==1)
	{
    
    
		pBoxText = (CEdit*)GetDlgItem(IDC_EDIT1);
		str_text.Format(_T("%d"), cnt++);
		pBoxText->SetWindowText(str_text);
	}

}

When I first started searching online for how to create a thread through the AfxBeginThread() function, and how to call global variables and modify the values ​​of controls on the interface through the thread function, I couldn't find any ready-made network information. It wasn't until I found a blog about this pointer that I realized it was This is achieved by using your own defined thread function and the parameters that need to be passed as input parameters of the AfxBeginThread() function.

Guess you like

Origin blog.csdn.net/alansss/article/details/105317716