在std :: thread中打开MFC对话框
我想显示一个对话框来通知用户应用程序正忙。为了避免阻塞主线程,我想使用std ::线程来显示对话框。请看下面的代码:在std :: thread中打开MFC对话框
InProcDlg inProcess;
std::thread t([ &inProcess ] {
inProcess.DoModal();
delete inProcess;
});
// wait till process fished
::PostMessage(inProcess.m_hWnd, WM_USER + 1, 0, 0);
if (t.joinable()){
t.join();
}
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;
}
运行这段代码正确所示的对话框。该对话框也关闭,但主对话框不显示,应用程序挂起CreateRunDlgIndirect()
。试着介入,同时设置一些断点,主对话框再次正确显示。很奇怪。我会非常乐意提供任何建议,我必须深入研究。
在接下来的步骤中,我还想通过发送一个指示当前进程状态的整数向用户显示进程。
int *percent;
::PostMessage(inProcess.m_hWnd, WM_USER + 2, 0, reinterpret_cast<LPARAM>(percent));
在发送或发布消息之前,我如何获得对话已存在的证据? 我使用Visual Studio 2013年
我能想到的两种方式做到这一点:
无模式对话框
https://www.codeproject.com/Articles/1651/Tutorial-Modeless-Dialogs-with-MFC
用户线程(UI线程)
使用CWinThread创建一个兄弟到主UI线程(CWinApp)。最重要的是分配一个指向一个对话框的CWinThread :: m_pMainWnd成员。如果对话框是Modal,则在调用DoModal之后立即返回FALSE,并返回TRUE for Modeless。
class CMainFrame : public CFrameWnd {
// pointer to thread
CWinThread* m_pUserThread;
}
启动线程
m_pUserThread = AfxBeginThread(RUNTIME_CLASS(CUserThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
m_pUserThread->m_bAutoDelete = TRUE;
m_pUserThread->ResumeThread();
HEADR文件**
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;
}
源文件
#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();
}
来终止线程
// post quit message to thread
m_pUserThread->PostThreadMessage(WM_QUIT,0,0);
// wait until thread termineates
::WaitForSingleObject(m_pUserThread->m_hThread,INFINITE);
对于这两种方法,我会强烈建议使对话框,最上面的窗口:
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;
}
恐怕,这不会像[本评论]中所解释的那样工作(http://stackoverflow.com/questions/41407418/open-a-mfc-dialog-in-a-stdthread?noredirect=1#comment70025977_41407418 )。 – IInspectable
看一看:http://stackoverflow.com/questions/1669017/how-to-create- a-mfc-dialog-with-a-progress-bar-in-a-separate-thread – dwo
是否删除inProcess;甚至编译?无论如何,放弃它 - 这是没有道理的。 –
反过来做它更好,通常也更容易 - 在主UI线程上显示对话框,在工作线程上运行繁忙处理。 –