阅读背景:

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

来源:互联网 



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

通常销毁或者关闭窗口会用如下函数:
[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]会是正确的销毁窗口的方法。

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

通常销毁或者关闭窗口会用如下函数:
[1



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: