簡體   English   中英

在 std::thread 中打開 MFC 對話框

[英]Open a MFC dialog in a std::thread

我想顯示一個對話框來通知用戶應用程序正忙。 為了避免阻塞主線程,我想使用 std::thread 來顯示對話框。 考慮以下代碼:

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

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 成員分配一個指向 Dialog 的指針。 如果對話框是模態的,則在調用 DoModal 后立即返回 FALSE,對於無模態返回 TRUE。

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();

頭文件**

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM