您的位置:首页 > 其它

关于子线程中销毁主线程窗口的问题

2016-10-30 22:47 225 查看
关于子线程中销毁主线程窗口的问题

通常销毁或者关闭窗口会用如下函数:
[1] CWnd::DestroyWindow()
[2] CFrameWnd::OnClose()
[3] ::SendMessage(hWnd,WM_SYSCOMMAND,SC_CLOSE,0);
或者::SendMessage(hWnd,WM_CLOSE,NULL,NULL);

之间的关系如下:
After runing the function sendMessage(),thefunction OnClose() will be excuted;
in the function OnClose() , DestroyWindow() will be called in the end

/////////////////////////////////////////////////////////////////////////////
// CFrameWnd closing down

void CFrameWnd::OnClose()
{
if (m_lpfnCloseProc != NULL)
{
// if there is a close proc, then defer to it, and return
// after calling it so the frame itself does not close.
(*m_lpfnCloseProc)(this);
return;
}

// Note: only queries the active document
CDocument* pDocument = GetActiveDocument();
if (pDocument != NULL && !pDocument->CanCloseFrame(this))
{
// document can't close right now -- don't close it
return;
}
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->m_pMainWnd == this)
{
CDataRecoveryHandler *pHandler = pApp->GetDataRecoveryHandler();
if ((pHandler != NULL) && (pHandler->GetShutdownByRestartManager()))
{
// If the application is being shut down by the Restart Manager, do
// a final autosave. This will mark all the documents as not dirty,
// so the SaveAllModified call below won't prompt for save.
pHandler->AutosaveAllDocumentInfo();
pHandler->SaveOpenDocumentList();
}

// attempt to save all documents
if (pDocument == NULL && !pApp->SaveAllModified())
return; // don't close it

if ((pHandler != NULL) && (!pHandler->GetShutdownByRestartManager()))
{
// If the application is not being shut down by the Restart Manager,
// delete any autosaved documents since everything is now fully saved.
pHandler->DeleteAllAutosavedFiles();
}

// hide the application's windows before closing all the documents
pApp->HideApplication();

// close all documents first
pApp->CloseAllDocuments(FALSE);

// don't exit if there are outstanding component objects
if (!AfxOleCanExitApp())
{
// take user out of control of the app
AfxOleSetUserCtrl(FALSE);

// don't destroy the main window and close down just yet
// (there are outstanding component (OLE) objects)
return;
}

// there are cases where destroying the documents may destroy the
// main window of the application.
if (!afxContextIsDLL && pApp->m_pMainWnd == NULL)
{
AfxPostQuitMessage(0);
return;
}
}

// detect the case that this is the last frame on the document and
// shut down with OnCloseDocument instead.
if (pDocument != NULL && pDocument->m_bAutoDelete)
{
BOOL bOtherFrame = FALSE;
POSITION pos = pDocument->GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = pDocument->GetNextView(pos);
ENSURE_VALID(pView);
if (pView->GetParentFrame() != this)
{
bOtherFrame = TRUE;
break;
}
}
if (!bOtherFrame)
{
pDocument->OnCloseDocument();
return;
}

// allow the document to cleanup before the window is destroyed
pDocument->PreCloseFrame(this);
}

// then destroy the window
DestroyWindow();
}

//////////////////////

BOOL CWnd::DestroyWindow()
{
CWnd* pWnd;
CHandleMap* pMap;
HWND hWndOrig;
BOOL bResult;

if ((m_hWnd == NULL) && (m_pCtrlSite == NULL))
return FALSE;

bResult = FALSE;
pMap = NULL;
pWnd = NULL;
hWndOrig = NULL;
if (m_hWnd != NULL)
{
pMap = afxMapHWND();
ENSURE(pMap != NULL);
pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
#ifdef _DEBUG
hWndOrig = m_hWnd;
#endif
}

#ifdef _AFX_NO_OCC_SUPPORT
if (m_hWnd != NULL)
bResult = ::DestroyWindow(m_hWnd);
#else //_AFX_NO_OCC_SUPPORT
if ((m_hWnd != NULL) || (m_pCtrlSite != NULL))
{
if (m_pCtrlSite == NULL)
bResult = ::DestroyWindow(m_hWnd);
else
bResult = m_pCtrlSite->DestroyControl();
}
#endif //_AFX_NO_OCC_SUPPORT

if (hWndOrig != NULL)
{
// Note that 'this' may have been deleted at this point,
// (but only if pWnd != NULL)
if (pWnd != NULL)
{
// Should have been detached by OnNcDestroy
#ifdef _DEBUG
ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);
#endif
}
else
{
#ifdef _DEBUG
ASSERT(m_hWnd == hWndOrig);
#endif
// Detach after DestroyWindow called just in case
Detach();
}
}

return bResult;
}

在子线程里面想关闭或销毁主窗口,不能用方法[1][2],因为在子线程中调用DestroyWindow()的时候 ,
pMap = afxMapHWND()会出现问题:pMap = 0.而正常情况下要保证ENSURE(pMap != NULL);
而方法[3]会是正确的销毁窗口的方法。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: