基于MFC的在线程里创建模态/非模态对话框(使用工作线程和界面线程)

工作线程

首先是创建模态的对话框:

要清楚一点:DoModal函数是阻塞的,程序执行到这里就停了,直到把该模态对话框关闭之后,才继续执行。而非模态对话框是不管对话框创建完消没消失,程序都会向下走。

UINT _cdecl  C多线程Dlg::ThreadProc(LPVOID lpParameter) 
{
 C多线程Dlg *pThisDlg = (C多线程Dlg *)lpParameter;//获取当前主对话框的指针,要进行强转
 CTestDlg dlg1;
 dlg1.DoModal();//在线程函数中创建模态的对话框,把dlg对象显示为模态对话框
 return 0;
}
void C多线程Dlg::OnBnClickedBtn()
{
CWinThread *pThread = AfxBeginThread(ThreadProc,this);
}

线程退出了,线程函数就结束了,响应申请的资源就释放了,所以DoModal阻塞在那儿模态对话框不会退出,非模态对话框就自然而然的消失了

工作线程没有消息循环,对话框界面的刷新工作,包括接受用户的鼠标键盘操作,都不会响应,但我们可以给他一个消息循环,但如果都这样做了,那为什么不去用界面线程呢,界面线程考虑的会更全面。

创建非模态对话框的代码如下:

UINT _cdecl  C多线程Dlg::ThreadProc(LPVOID lpParameter) 
{
 C多线程Dlg *pThisDlg = (C多线程Dlg *)lpParameter;//获取当前主对话框的指针,要进行强转
 CTestDlg *pTestDlg = new CTestDlg(); //创建指针非模态对话框才可以正常显示,开辟一个存放CTestDlg类型的存储空间,返回一个指向该存储空间的地址(即指针) 可以多处使用,和直接创建相比需要手动销毁,
 //pTestDlg->Create(IDD_DIALOG1,pThisDlg);//参数Ⅰ创建的非模态对话框模板的ID 参数Ⅱ父窗口指针  但这个语句是不对的 两个对话框的资源没有在一个线程中,可以设为NULL,以桌面为其父窗口
 pTestDlg->Create(IDD_DIALOG1,NULL);
 pTestDlg->ShowWindow(SW_SHOW);//显示对话框
//以下几条语句(消息循环):从当前线程的消息队列中做消息处理
 MSG msg = {0};
 while(GetMessage(&msg, NULL, 0, 0))//无限的取消息
 {
 TranslateMessage(&msg);//消息的转换
 DispatchMessage(&msg);//消息的分发
 }

不加消息循环语句,对话框弹出几毫秒就随着线程结束消失了。

如何创建界面线程?

第一步:在解决方案中右击项目,选择添加,选择类,之后按下图选择,点击添加,
在这里插入图片描述
在这里插入图片描述如此我们就向我们的工程中插入了一个CWinThread的子类。
第二步:重载InitInstance函数,在InitInstance函数(界面线程的初始化函数)中进行界面的创建。
先在UIThreadApp.cpp中添加头文件#include “TestDlg.h”,之后在函数中添加代码

BOOL CUIThreadApp::InitInstance()
{
 // TODO: 在此执行任意逐线程初始化
 CTestDlg dlg;
 dlg.DoModal();
 return TRUE;
}

第三步:调用AfxBeginThread函数开启界面线程。
在主对话框.cpp文件中添加头文件#include “UIThreadApp.h”,

首先创建模态对话框:

点击响应函数:
void C多线程Dlg::OnBnClickedBtn()
{
 //m_Num = 123;
 //CWinThread *pThread = AfxBeginThread(ThreadProc,this);
 AfxBeginThread(RUNTIME_CLASS(CUIThreadApp));//参数 CWinThread类的子类,该函数会实例化该类的对象并让界面线程运行起来
}

界面线程初始化函数:
BOOL CUIThreadApp::InitInstance()
{
 // TODO: 在此执行任意逐线程初始化
 CTestDlg dlg;
 dlg.DoModal();
 return FALSE;//把TURE改为False 我们把模态框退出之后,界面线程就没有其存在的意义,我们就让它退出。设为TURE则会导致无法执行界面线程退出函数造成内存泄漏
}

创建非模态对话框

点击响应函数:
void C多线程Dlg::OnBnClickedBtn()
{
 AfxBeginThread(RUNTIME_CLASS(CUIThreadApp));//参数 CWinThread类的子类,该函数会实例化该类的对象并让界面线程运行起来
}
界面线程初始化函数:
BOOL CUIThreadApp::InitInstance()
{
 // TODO: 在此执行任意逐线程初始化
 CTestDlg *pTestDlg = new CTestDlg(); 
 pTestDlg->Create(IDD_DIALOG1,NULL);
 pTestDlg->ShowWindow(SW_SHOW);//显示对话框
 pTestDlg->RunModalLoop();//开启非模态框消息循环,没有就会一闪而过
 return FALSE;
}

猜你喜欢

转载自blog.csdn.net/qq_42308217/article/details/108421481