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



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

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


已标记关键词 清除标记
写了一个MFC DLL动态库。 在mfc dll里面添加了对话框资源,并且添加一个对话框类CDlg。 可以通过SetWindowsHookEx注入到序。 但是退出的时候,被注入序总是崩溃。 ---------- dll注入序 int DllLoad( HWND hWnd ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); int nRet = -1; dllHwnd = hWnd; HWND hwnd = FindWindowA(NULL, "Lingoes 灵格斯"); if ( NULL == hwnd ) { MessageBoxA(NULL, "获取序句柄失败", "xx", MB_OK); TRACE("获取序句柄失败!"); return -1; } DWORD pid = GetWindowThreadProcessId( hwnd, NULL ); if ( NULL == inHook ) { inHook = SetWindowsHookEx( WH_GETMESSAGE, GameProc, hInstDll, pid ); } nRet = 0; return nRet; } ---------- dll卸载序 void DllUnLoad() { if ( NULL != inHook ) { UnhookWindowsHookEx( inHook ); inHook = NULL; } } ---------- 注入处理函数 LRESULT CALLBACK GameProc(int nCode,WPARAM wParam, LPARAM lParam) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); PMSG pMsg = (PMSG)lParam; if ( pMsg->message == WM_KEYUP ) { if ( pMsg->wParam == VK_HOME ) { if ( NULL == pDlg ) { CWnd *pCwnd = CWnd::GetForegroundWindow(); pDlg = new CDlg(); pDlg->Create( IDD_DLG, pCwnd); pDlg->ShowWindow(SW_SHOW); } else { if ( pDlg->IsWindowVisible() ) pDlg->ShowWindow(FALSE); else pDlg->ShowWindow(TRUE); } } } return CallNextHookEx(0,nCode,wParam,lParam); } ---------- int CDlgDllApp::ExitInstance() { if ( NULL != pDlg ) { //pDlg->DestroyWindow(); delete pDlg; pDlg = NULL; } return CWinApp::ExitInstance(); } ---------- ---------- 在网上找了好多例,都只是简单的调了个.doModel(); 具体在钩函数里面生成并显示一个对话框的例太少,能找到的也试了下,都是能注入,但注入序一关闭,被注入的序也跟着关闭了。还有一个大大的提示求解答。 ---------- Debug Assertion Failed! File:f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp line:1019 跟进去后发现: if (m_hWnd != NULL) { pMap = afxMapHWND(); ENSURE(pMap != NULL); pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd); } 求各位给个提示,如果注入后不调出对话框,直接退出,被注入序能运行,只要调用对话框资源后,就不行了。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页