跟一跟AfxBeginThread的源码就可以很容易的发现,它调用了_beginthreadex,注意这家伙传递的可不是你传进去的函数函数指针,它传的是_AfxThreadEntry和一个_AFX_THREAD_STARTUP的结构,那我们的函数指针和参数呢??哦,原来都被封装到_AFX_THREAD_STARTUP里面了,那AfxThreadEntry这家伙想干什么。。
它调用了API CreateThread,传递的是_threadstartex和_ptiddata结构的参数,啊,原来上面的指针和参数又被打包成一个参数了,那最后调用的效果还会和原来的一样吗。。
原来在threadstartex中它又开始拆包工作了,最后和TCP/IP协议栈一样,拆出了我们的函数和参数
_endthreadex (
( (unsigned (__CLR_OR_STD_CALL *)(void *))(((_ptiddata)ptd)->_initaddr) )
( ((_ptiddata)ptd)->_initarg ) ) ;
这是threadex.c里面的代码。。这不是在拆包吗~~MFC的框架在模仿TCP/IP结构,这样做是。。?为了传递足够的信息!!保证线程的安全~~~
UINT APIENTRY _AfxThreadEntry(void* pParam)
{
_AFX_THREAD_STARTUP* pStartup = (_AFX_THREAD_STARTUP*)pParam;
ASSERT(pStartup != NULL);
ASSERT(pStartup->pThreadState != NULL);
ASSERT(pStartup->pThread != NULL);
ASSERT(pStartup->hEvent != NULL);
ASSERT(!pStartup->bError);
CWinThread* pThread = pStartup->pThread;
CWnd threadWnd;
TRY
{
// inherit parent's module state
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
pThreadState->m_pModuleState = pStartup->pThreadState->m_pModuleState;
// set current thread pointer for AfxGetThread
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pThread->m_pModuleState = pModuleState;
AFX_MODULE_THREAD_STATE* pState = pModuleState->m_thread;
pState->m_pCurrentWinThread = pThread;
// forced initialization of the thread
AfxInitThread();
// thread inherits app's main window if not already set
CWinApp* pApp = AfxGetApp();
if (pApp != NULL &&
pThread->m_pMainWnd == NULL && pApp->m_pMainWnd->GetSafeHwnd() != NULL)
{
// just attach the HWND
threadWnd.Attach(pApp->m_pMainWnd->m_hWnd);
pThread->m_pMainWnd = &threadWnd;
}
}
CATCH_ALL(e)
{
// Note: DELETE_EXCEPTION(e) not required.
// exception happened during thread initialization!!
TRACE(traceAppMsg, 0, "Warning: Error during thread initialization!\n");
// set error flag and allow the creating thread to notice the error
threadWnd.Detach();
pStartup->bError = TRUE;
VERIFY(::SetEvent(pStartup->hEvent));
AfxEndThread((UINT)-1, FALSE);
ASSERT(FALSE); // unreachable
}
END_CATCH_ALL
// pStartup is invlaid after the following
// SetEvent (but hEvent2 is valid)
HANDLE hEvent2 = pStartup->hEvent2;
// allow the creating thread to return from CWinThread::CreateThread
VERIFY(::SetEvent(pStartup->hEvent));
// wait for thread to be resumed
VERIFY(::WaitForSingleObject(hEvent2, INFINITE) == WAIT_OBJECT_0);
::CloseHandle(hEvent2);
// first -- check for simple worker thread
DWORD nResult = 0;
if (pThread->m_pfnThreadProc != NULL)
{
nResult = (*pThread->m_pfnThreadProc)(pThread->m_pThreadParams);//注意!!这边就调用我们传递的函数啦
ASSERT_VALID(pThread);
}
// else -- check for thread with message loop
else if (!pThread->InitInstance())
{
ASSERT_VALID(pThread);
nResult = pThread->ExitInstance();
}
else
{
// will stop after PostQuitMessage called
ASSERT_VALID(pThread);
nResult = pThread->Run();
}
// cleanup and shutdown the thread
threadWnd.Detach();
AfxEndThread(nResult);
return 0; // not reached
}
void AFXAPI AfxInitThread()//设置个消息钩子,hook之后它还想干什么?这个我就不知道了。。
{
if (!afxContextIsDLL)
{
// set message filter proc
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState->m_hHookOldMsgFilter == NULL);
pThreadState->m_hHookOldMsgFilter = ::SetWindowsHookEx(WH_MSGFILTER,
_AfxMsgFilterHook, NULL, ::GetCurrentThreadId());
}
}
上面的代码很清楚了,就一封包拆包过程,看了此文你就知道李久进讲的MFC线程是怎么来的了。。都是慢悠悠跟出来的~~
_AfxMsgFilterHook这家伙长这个样
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);
}
完了,一天都在跟MFC源码,再跟下回学校了,刚听说明天不加班,哈哈。。
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 (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();
ENSURE(pThreadState);
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
}
头晕,回校~~