下面是示例代碼.
從CWinThread派生一個CUIThread類,可以利用VS向導生成,再添加一個成員:HWND m_hParentWnd.
建立一個對話框類CUIChildDlg,同樣用VS向導生成.
子視窗所在的線程.
class CUIThread : public CWinThread
{
DECLARE_DYNCREATE(CUIThread)
protected:
CUIThread(); // protected constructor used by dynamic creation
virtual ~CUIThread();
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
DECLARE_MESSAGE_MAP()
HWND m_hParentWnd; //注意,它是父視窗句柄,不能是CWnd*對象.
};
線上程中建立對話框視窗.
BOOL CUIWinThread::InitInstance()
// TODO: perform and per-thread initialization here
ASSERT(::IsWindow(m_ hParentWnd));
CWnd* pParent = CWnd::FromHandle(m_hParentWnd);//注意這行
CUIChildDlg* pDlg = new CUIChildDlg(pParent);
pDlg->Create(CUIChildDlg::IDD, pParent);
pDlg->ShowWindow(SW_SHOW);
return TRUE;
}
在這個函數中,建立了一個對話框,作為主視窗的子視窗.
注意這個FromHandle的調用,他傳回一個CWnd對象.
這樣建立的視窗不會報錯.如果直接将主視窗對象傳遞過來,而不是通過調用FromHandle擷取,則調用pDlg->Create會報錯,在調試版本中會彈出一個視窗,指出錯誤位置.
CUIChildDlg是利用向導随便寫的一個對話框.注意要重載下面這個函數.
void CUIChildDlg::OnNcDestroy()
CDialog::OnNcDestroy();
// TODO: Add your message handler code here
::PostQuitMessage(0);//為了使線程自動退出.
下面代碼是CWinApp派生類,主視窗在這個類中建立.
BOOL CMFCSingleDocTestApp::InitInstance()
... …
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_SHOW);//主視窗
m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
m_pUIThread = (CUIWinThread*)AfxBeginThread(RUNTIME_CLASS(CUIWinThread),
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);//建立後先不要啟動.
m_pUIThread->m_hParentWnd = m_pMainWnd->m_hWnd;//主視窗句柄.
m_pUIThread->ResumeThread();
退出函數實作.
int CMFCSingleDocTestApp::ExitInstance()
//TODO: handle additional resources you may have added
AfxOleTerm(FALSE);
ASSERT(NULL != m_pUIThread);
::WaitForSingleObject(m_pUIThread->m_hThread, INFINITE);
return CWinAppEx::ExitInstance();
等待函數是必須的,這是為了等待子視窗線程退出後父視窗線程再退出.
在測試中發現,關閉主視窗之前隻能保證先關閉子視窗,但退出主線程之前并不能保證子視窗線程一定會退出,這可能會導緻某些資源不能正确釋放,是以這裡要調用等待函數,進而保證子視窗線程能夠正常退出.
跨線程父子視窗的好處是建立子視窗阻塞時不會影響父視窗的運作.例如啟動程式時,建立子視窗過程中由于加載太多内容而阻塞,導緻父視窗無法操作,分屬不同線程後,父視窗運作不受影響,它仍然可以正常啟動,最大最小化,移動,響應滑鼠消息等等.
但也不完全是這樣,程式運作起來之後,子視窗也會使用父視窗所在的線程消息循環,如果子視窗阻塞,同樣會導緻父視窗阻塞.
本文轉自jetyi51CTO部落格,原文連結:http://blog.51cto.com/jetyi/1074315 ,如需轉載請自行聯系原作者