⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thrdcore.cpp

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// CWinThread default implementation

BOOL CWinThread::InitInstance()
{
	ASSERT_VALID(this);

	return FALSE;   // by default don't enter run loop
}

// main running routine until thread exits
int CWinThread::Run()
{
	ASSERT_VALID(this);

	// for tracking the idle time state
	BOOL bIdle = TRUE;
	LONG lIdleCount = 0;

	// acquire and dispatch messages until a WM_QUIT message is received.
	for (;;)
	{
		// phase1: check to see if we can do idle work
		while (bIdle &&
			!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
		{
			// call OnIdle while in bIdle state
			if (!OnIdle(lIdleCount++))
				bIdle = FALSE; // assume "no idle" state
		}

		// phase2: pump messages while available
		do
		{
			// pump message, but quit on WM_QUIT
			if (!PumpMessage())
				return ExitInstance();

			// reset "no idle" state after pumping "normal" message
			if (IsIdleMessage(&m_msgCur))
			{
				bIdle = TRUE;
				lIdleCount = 0;
			}

		} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
	}

	ASSERT(FALSE);  // not reachable
}

BOOL CWinThread::IsIdleMessage(MSG* pMsg)
{
	// Return FALSE if the message just dispatched should _not_
	// cause OnIdle to be run.  Messages which do not usually
	// affect the state of the user interface and happen very
	// often are checked for.

	// redundant WM_MOUSEMOVE and WM_NCMOUSEMOVE
	if (pMsg->message == WM_MOUSEMOVE || pMsg->message == WM_NCMOUSEMOVE)
	{
		// mouse move at same position as last mouse move?
		if (m_ptCursorLast == pMsg->pt && pMsg->message == m_nMsgLast)
			return FALSE;

		m_ptCursorLast = pMsg->pt;  // remember for next time
		m_nMsgLast = pMsg->message;
		return TRUE;
	}

	// WM_PAINT and WM_SYSTIMER (caret blink)
	return pMsg->message != WM_PAINT && pMsg->message != 0x0118;
}

int CWinThread::ExitInstance()
{
	ASSERT_VALID(this);
	ASSERT(AfxGetApp() != this);

	int nResult = m_msgCur.wParam;  // returns the value from PostQuitMessage
	return nResult;
}

BOOL CWinThread::OnIdle(LONG lCount)
{
	ASSERT_VALID(this);

#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
	// check MFC's allocator (before idle)
	if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_CHECK_ALWAYS_DF)
		ASSERT(AfxCheckMemory());
#endif

	if (lCount <= 0)
	{
		// send WM_IDLEUPDATECMDUI to the main window
		CWnd* pMainWnd = m_pMainWnd;
		if (pMainWnd != NULL && pMainWnd->m_hWnd != NULL &&
			pMainWnd->IsWindowVisible())
		{
			AfxCallWndProc(pMainWnd, pMainWnd->m_hWnd,
				WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0);
			pMainWnd->SendMessageToDescendants(WM_IDLEUPDATECMDUI,
				(WPARAM)TRUE, 0, TRUE, TRUE);
		}
		// send WM_IDLEUPDATECMDUI to all frame windows
		AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
		CFrameWnd* pFrameWnd = pState->m_frameList;
		while (pFrameWnd != NULL)
		{
			if (pFrameWnd->m_hWnd != NULL && pFrameWnd != pMainWnd)
			{
				if (pFrameWnd->m_nShowDelay == SW_HIDE)
					pFrameWnd->ShowWindow(pFrameWnd->m_nShowDelay);
				if (pFrameWnd->IsWindowVisible() ||
					pFrameWnd->m_nShowDelay >= 0)
				{
					AfxCallWndProc(pFrameWnd, pFrameWnd->m_hWnd,
						WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0);
					pFrameWnd->SendMessageToDescendants(WM_IDLEUPDATECMDUI,
						(WPARAM)TRUE, 0, TRUE, TRUE);
				}
				if (pFrameWnd->m_nShowDelay > SW_HIDE)
					pFrameWnd->ShowWindow(pFrameWnd->m_nShowDelay);
				pFrameWnd->m_nShowDelay = -1;
			}
			pFrameWnd = pFrameWnd->m_pNextFrameWnd;
		}
	}
	else if (lCount >= 0)
	{
		AFX_MODULE_THREAD_STATE* pState = _AFX_CMDTARGET_GETSTATE()->m_thread;
		if (pState->m_nTempMapLock == 0)
		{
			// free temp maps, OLE DLLs, etc.
			AfxLockTempMaps();
			AfxUnlockTempMaps();
		}
	}

#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
	// check MFC's allocator (after idle)
	if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_CHECK_ALWAYS_DF)
		ASSERT(AfxCheckMemory());
#endif

	return lCount < 0;  // nothing more to do if lCount >= 0
}

void CWinThread::DispatchThreadMessage(MSG* pMsg)
{
	DispatchThreadMessageEx(pMsg);
}

BOOL CWinThread::DispatchThreadMessageEx(MSG* pMsg)
{
	const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
	const AFX_MSGMAP_ENTRY* lpEntry;

#ifdef _AFXDLL
	for (/* pMessageMap already init'ed */; pMessageMap != NULL;
		pMessageMap = (*pMessageMap->pfnGetBaseMap)())
#else
	for (/* pMessageMap already init'ed */; pMessageMap != NULL;
		pMessageMap = pMessageMap->pBaseMap)
#endif

	{
		// Note: catch not so common but fatal mistake!!
		//      BEGIN_MESSAGE_MAP(CMyThread, CMyThread)
#ifdef _AFXDLL
		ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
#else
		ASSERT(pMessageMap != pMessageMap->pBaseMap);
#endif

		if (pMsg->message < 0xC000)
		{
			// constant window message
			if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
				pMsg->message, 0, 0)) != NULL)
				goto LDispatch;
		}
		else
		{
			// registered windows message
			lpEntry = pMessageMap->lpEntries;
			while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
			{
				UINT* pnID = (UINT*)(lpEntry->nSig);
				ASSERT(*pnID >= 0xC000);
					// must be successfully registered
				if (*pnID == pMsg->message)
					goto LDispatch;
				lpEntry++;      // keep looking past this one
			}
		}
	}
	return FALSE;

LDispatch:
	union MessageMapFunctions mmf;
	mmf.pfn = lpEntry->pfn;

	// always posted, so return value is meaningless

	(this->*mmf.pfn_THREAD)(pMsg->wParam, pMsg->lParam);
	return TRUE;
}

BOOL CWinThread::PreTranslateMessage(MSG* pMsg)
{
	ASSERT_VALID(this);

	// if this is a thread-message, short-circuit this function
	if (pMsg->hwnd == NULL && DispatchThreadMessageEx(pMsg))
		return TRUE;

	// walk from target to main window
	CWnd* pMainWnd = AfxGetMainWnd();
	if (CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))
		return TRUE;

	// in case of modeless dialogs, last chance route through main
	//   window's accelerator table
	if (pMainWnd != NULL)
	{
		 CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
		 if (pWnd->GetTopLevelParent() != pMainWnd)
			return pMainWnd->PreTranslateMessage(pMsg);
	}

	return FALSE;   // no special processing
}

LRESULT CWinThread::ProcessWndProcException(CException*, const MSG* pMsg)
{
	if (pMsg->message == WM_CREATE)
	{
		return -1;  // just fail
	}
	else if (pMsg->message == WM_PAINT)
	{
		// force validation of window to prevent getting WM_PAINT again
		ValidateRect(pMsg->hwnd, NULL);
		return 0;
	}
	return 0;   // sensible default for rest of commands
}

/////////////////////////////////////////////////////////////////////////////
// Message Filter processing (WH_MSGFILTER)

LRESULT CALLBACK _AfxMsgFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
	CWinThread* pThread;
	if (afxContextIsDLL || (code < 0 && code != MSGF_DDEMGR) ||
		(pThread = AfxGetThread()) == NULL)
	{
		return ::CallNextHookEx(_afxThreadState->m_hHookOldMsgFilter,
			code, wParam, lParam);
	}
	ASSERT(pThread != NULL);
	return (LRESULT)pThread->ProcessMessageFilter(code, (LPMSG)lParam);
}

AFX_STATIC BOOL AFXAPI IsHelpKey(LPMSG lpMsg)
	// return TRUE only for non-repeat F1 keydowns.
{
	return lpMsg->message == WM_KEYDOWN &&
		   lpMsg->wParam == VK_F1 &&
		   !(HIWORD(lpMsg->lParam) & KF_REPEAT) &&
		   GetKeyState(VK_SHIFT) >= 0 &&
		   GetKeyState(VK_CONTROL) >= 0 &&
		   GetKeyState(VK_MENU) >= 0;
}

AFX_STATIC inline BOOL IsEnterKey(LPMSG lpMsg)
	{ return lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_RETURN; }

AFX_STATIC inline BOOL IsButtonUp(LPMSG lpMsg)
	{ return lpMsg->message == WM_LBUTTONUP; }

BOOL CWinThread::ProcessMessageFilter(int code, LPMSG lpMsg)
{
	if (lpMsg == NULL)
		return FALSE;   // not handled

	CFrameWnd* pTopFrameWnd;
	CWnd* pMainWnd;
	CWnd* pMsgWnd;
	switch (code)
	{
	case MSGF_DDEMGR:
		// Unlike other WH_MSGFILTER codes, MSGF_DDEMGR should
		//  never call the next hook.
		// By returning FALSE, the message will be dispatched
		//  instead (the default behavior).
		return FALSE;

	case MSGF_MENU:
		pMsgWnd = CWnd::FromHandle(lpMsg->hwnd);
		if (pMsgWnd != NULL)
		{
			pTopFrameWnd = pMsgWnd->GetTopLevelFrame();
			if (pTopFrameWnd != NULL && pTopFrameWnd->IsTracking() &&
				pTopFrameWnd->m_bHelpMode)
			{
				pMainWnd = AfxGetMainWnd();
				if ((m_pMainWnd != NULL) && (IsEnterKey(lpMsg) || IsButtonUp(lpMsg)))
				{
					pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
					return TRUE;
				}
			}
		}
		// fall through...

	case MSGF_DIALOGBOX:    // handles message boxes as well.
		pMainWnd = AfxGetMainWnd();
		if (afxData.nWinVer < 0x333 && pMainWnd != NULL && IsHelpKey(lpMsg))
		{
			pMainWnd->SendMessage(WM_COMMAND, ID_HELP);
			return TRUE;
		}
		if (code == MSGF_DIALOGBOX && m_pActiveWnd != NULL &&
			lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST)
		{
			// need to translate messages for the in-place container
			_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
			if (pThreadState->m_bInMsgFilter)
				return FALSE;
			pThreadState->m_bInMsgFilter = TRUE;    // avoid reentering this code
			MSG msg = *lpMsg;
			if (m_pActiveWnd->IsWindowEnabled() && PreTranslateMessage(&msg))
			{
				pThreadState->m_bInMsgFilter = FALSE;
				return TRUE;
			}
			pThreadState->m_bInMsgFilter = FALSE;    // ok again
		}
		break;
	}

	return FALSE;   // default to not handled
}

/////////////////////////////////////////////////////////////////////////////
// Access to m_pMainWnd & m_pActiveWnd

CWnd* CWinThread::GetMainWnd()
{
	if (m_pActiveWnd != NULL)
		return m_pActiveWnd;    // probably in-place active

	// when not inplace active, just return main window
	if (m_pMainWnd != NULL)
		return m_pMainWnd;

	return CWnd::GetActiveWindow();
}

/////////////////////////////////////////////////////////////////////////////
// CWinThread implementation helpers

BOOL CWinThread::PumpMessage()
{
	ASSERT_VALID(this);

	if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
	{
#ifdef _DEBUG
		if (afxTraceFlags & traceAppMsg)
			TRACE0("CWinThread::PumpMessage - Received WM_QUIT.\n");
		m_nDisablePumpCount++; // application must die
			// Note: prevents calling message loop things in 'ExitInstance'
			// will never be decremented
#endif
		return FALSE;
	}

#ifdef _DEBUG
	if (m_nDisablePumpCount != 0)
	{
		TRACE0("Error: CWinThread::PumpMessage called when not permitted.\n");
		ASSERT(FALSE);
	}
#endif

#ifdef _DEBUG
	if (afxTraceFlags & traceAppMsg)
		_AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
#endif

	// process this message

	if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
	{
		::TranslateMessage(&m_msgCur);
		::DispatchMessage(&m_msgCur);
	}
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CWinThread diagnostics

#ifdef _DEBUG
void CWinThread::AssertValid() const
{
	CCmdTarget::AssertValid();
}

void CWinThread::Dump(CDumpContext& dc) const
{
	CCmdTarget::Dump(dc);

	dc << "m_pThreadParams = " << m_pThreadParams;
	dc << "\nm_pfnThreadProc = " << (void*)m_pfnThreadProc;
	dc << "\nm_bAutoDelete = " << m_bAutoDelete;
	dc << "\nm_hThread = " << (void*)m_hThread;
	dc << "\nm_nThreadID = " << m_nThreadID;
	dc << "\nm_nDisablePumpCount = " << m_nDisablePumpCount;
	if (AfxGetThread() == this)
		dc << "\nm_pMainWnd = " << m_pMainWnd;

	dc << "\nm_msgCur = {";
	dc << "\n\thwnd = " << (UINT)m_msgCur.hwnd;
	dc << "\n\tmessage = " << (UINT)m_msgCur.message;
	dc << "\n\twParam = " << (UINT)m_msgCur.wParam;
	dc << "\n\tlParam = " << (void*)m_msgCur.lParam;
	dc << "\n\ttime = " << m_msgCur.time;
	dc << "\n\tpt = " << CPoint(m_msgCur.pt);
	dc << "\n}";

	dc << "\nm_pThreadParams = " << m_pThreadParams;
	dc << "\nm_pfnThreadProc = " << (void*)m_pfnThreadProc;
	dc << "\nm_ptCursorLast = " << m_ptCursorLast;
	dc << "\nm_nMsgLast = " << m_nMsgLast;

	dc << "\n";
}
#endif

#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif

IMPLEMENT_DYNAMIC(CWinThread, CCmdTarget)

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -