[英]Open a MFC dialog in a std::thread
I would like to show a dialog to inform the user that the application is busy.我想显示一个对话框来通知用户应用程序正忙。 To avoid blocking of the main thread, I was thinking to use a std::thread to show the dialog.为了避免阻塞主线程,我想使用 std::thread 来显示对话框。 Consider the following code:考虑以下代码:
InProcDlg inProcess;
std::thread t([ &inProcess ] {
inProcess.DoModal();
delete inProcess;
});
// wait till process has finished
::PostMessage(inProcess.m_hWnd, WM_USER + 1, 0, 0);
if (t.joinable()){
t.join();
}
InProcDlg.cpp InProcDlg.cpp
BEGIN_MESSAGE_MAP(InProcDlg, CDialogEx)
...
ON_MESSAGE(WM_USER + 1, &InProcDlg::close)
END_MESSAGE_MAP()
LRESULT InProcDlg::close(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam, lParam);
EndDialog(1);
return 0;
}
Running this code the dialog is shown properly.运行此代码,对话框显示正确。 The dialog is also closed, but the main dialog is not shown, the application hangs in CreateRunDlgIndirect()
.该对话框也已关闭,但未显示主对话框,应用程序挂在CreateRunDlgIndirect()
。 Trying to step in, while setting some breakpoints the main dialog is shown properly back again.尝试介入,同时设置一些断点,主对话框再次正确显示。 Very strange.很奇怪。 I would be very happy for any advices where I have to dive deeper in.对于我必须深入研究的任何建议,我将非常高兴。
In the next step I would also like to show the process to the user, by sending an integer indicating the current state of process.在下一步中,我还想通过发送一个指示进程当前状态的整数向用户展示进程。
int *percent;
::PostMessage(inProcess.m_hWnd, WM_USER + 2, 0, reinterpret_cast<LPARAM>(percent));
How I can gain evidence that the dialog is already existing, before sending or posting a message?在发送或发布消息之前,我如何获得对话已经存在的证据? I'm using Visual Studio 2013.我正在使用 Visual Studio 2013。
I can think of two ways to do that:我可以想到两种方法来做到这一点:
Modeless dialog无模式对话框
https://www.codeproject.com/Articles/1651/Tutorial-Modeless-Dialogs-with-MFC https://www.codeproject.com/Articles/1651/Tutorial-Modeless-Dialogs-with-MFC
User thread (UI thread)用户线程(UI线程)
Creating a brother to the main UI thread (CWinApp) by using CWinThread.使用 CWinThread 创建主 UI 线程 (CWinApp) 的兄弟。 Most important is to assign CWinThread::m_pMainWnd member, with a pointer to a Dialog.最重要的是为 CWinThread::m_pMainWnd 成员分配一个指向 Dialog 的指针。 If the dialog is Modal you return FALSE right after the call to DoModal, and return TRUE for Modeless.如果对话框是模态的,则在调用 DoModal 后立即返回 FALSE,对于无模态返回 TRUE。
class CMainFrame : public CFrameWnd {
// pointer to thread
CWinThread* m_pUserThread;
}
start thread开始线程
m_pUserThread = AfxBeginThread(RUNTIME_CLASS(CUserThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED );
m_pUserThread->m_bAutoDelete = TRUE;
m_pUserThread->ResumeThread();
headr file**头文件**
class CUserThread : public CWinThread
{
DECLARE_DYNCREATE(CUserThread)
public:
CUserThread();
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CUserThread)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
protected:
virtual ~CUserThread();
// Generated message map functions
//{{AFX_MSG(CUserThread)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
CUserMsg* m_pDlg;
}
source file源文件
#define DO_MODAL
BOOL CUserThread::InitInstance()
{
#ifdef DO_MODAL
// create and assign Modeless dialog
CUserMsg dlg;
m_pMainWnd = &m_pDlg;
dlg.DoModal();
return FALSE;
#endif
#ifdnef DO_MODAL
// create and assign Modal dialog
m_pDlg = new CUserMsg();
m_pDlg->Create( IDD_USER_DLG, AfxGetMainWnd() );
m_pMainWnd = m_pDlg;
return TRUE;
#endif
}
int CUserThread::ExitInstance()
{
// check for null
m_pDlg->SendMessage( WM_CLOSE ) ;
delete m_pDlg;
return CWinThread::ExitInstance();
}
to terminate the thread终止线程
// post quit message to thread
m_pUserThread->PostThreadMessage(WM_QUIT,0,0);
// wait until thread termineates
::WaitForSingleObject(m_pUserThread->m_hThread,INFINITE);
For both ways I would highly recommend making the dialog as a top most window:对于这两种方式,我强烈建议将对话框设为最顶部的窗口:
BOOL CLicenseGenDlg::OnInitDialog() {
CDialog::OnInitDialog();
// TODO: Add extra initialization here
SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | WS_EX_TOPMOST );
return TRUE;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.