国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
GetDlgItem

GetDlgItem

轉(zhuǎn)自http://blog.csdn.net/loveghb/archive/2005/06/21/399784.aspx


由GetDlgItem函數(shù)想到的

 


我們?cè)谡{(diào)用CWnd::GetDlgItem()函數(shù)時(shí),MSDN告訴我們:The returned pointer may be temporary and should not be stored for later use.

中文意思就是:返回的指針可能是臨時(shí)的并且最好不要保存起來(lái)放到以后用。

猜測(cè):返回的指針既然可能是臨時(shí)的,那么可能是非臨時(shí)的(永久的),最好不要保存起來(lái)放到以后用(有時(shí)候可以保存起來(lái))

源碼面前,了無(wú)秘密。讓我們深入MFC源代碼去看個(gè)究竟。


 


先隨便建立一個(gè)Dialog程序,然后在窗體上拉一個(gè)按鈕,添加按鈕事件,在按鈕事件里寫(xiě)上如下代碼:GetDlgItem(IDC_BUTTON1); 然后給這行代碼加上斷點(diǎn)。好,我們開(kāi)始進(jìn)去看看,運(yùn)行程序,按下按鈕,程序就停在剛才的斷點(diǎn)出,然后F11進(jìn)去。

CWnd* CWnd::GetDlgItem(int nID) const

{

       ASSERT(::IsWindow(m_hWnd));


 


       if (m_pCtrlCont == NULL)

              return CWnd::FromHandle(::GetDlgItem(m_hWnd, nID));

       else

              return m_pCtrlCont->GetDlgItem(nID);

}


 


再跟蹤到紅色代碼中去:

CWnd* PASCAL CWnd::FromHandle(HWND hWnd)

{

       CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist

       ASSERT(pMap != NULL);

       CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd);


 


#ifndef _AFX_NO_OCC_SUPPORT

       pWnd->AttachControlSite(pMap);

#endif


 


       ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);

       return pWnd;

}


 


再一次跟蹤進(jìn)入紅色函數(shù)里去:

CHandleMap* PASCAL afxMapHWND(BOOL bCreate)

{

       AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

       if (pState->m_pmapHWND == NULL && bCreate)

       {

              BOOL bEnable = AfxEnableMemoryTracking(FALSE);

#ifndef _AFX_PORTABLE

              _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);

#endif

              pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),

                     offsetof(CWnd, m_hWnd));


 


#ifndef _AFX_PORTABLE

              AfxSetNewHandler(pnhOldHandler);

#endif

              AfxEnableMemoryTracking(bEnable);

       }

       return pState->m_pmapHWND;

}


 


看一下AFX_MODULE_THREAD_STATE的定義:

// AFX_MODULE_THREAD_STATE (local to thread *and* module)

class AFX_MODULE_THREAD_STATE : public CNoTrackObject

{

public:

       AFX_MODULE_THREAD_STATE();

       virtual ~AFX_MODULE_THREAD_STATE();


 


       // current CWinThread pointer

       CWinThread* m_pCurrentWinThread;


 


       // list of CFrameWnd objects for thread

       CTypedSimpleList<CFrameWnd*> m_frameList;


 


       // temporary/permanent map state

       DWORD m_nTempMapLock;           // if not 0, temp maps locked

       CHandleMap* m_pmapHWND;

       CHandleMap* m_pmapHMENU;

       CHandleMap* m_pmapHDC;

       CHandleMap* m_pmapHGDIOBJ;

       CHandleMap* m_pmapHIMAGELIST;


 


       // thread-local MFC new handler (separate from C-runtime)

       _PNH m_pfnNewHandler;


 


#ifndef _AFX_NO_SOCKET_SUPPORT

       // WinSock specific thread state

       HWND m_hSocketWindow;

#ifdef _AFXDLL

       CEmbeddedButActsLikePtr<CMapPtrToPtr> m_pmapSocketHandle;

       CEmbeddedButActsLikePtr<CMapPtrToPtr> m_pmapDeadSockets;

       CEmbeddedButActsLikePtr<CPtrList> m_plistSocketNotifications;

#else

       CMapPtrToPtr* m_pmapSocketHandle;

       CMapPtrToPtr* m_pmapDeadSockets;

       CPtrList* m_plistSocketNotifications;

#endif

#endif

};


 


看一下黃色的那一行代碼,很明顯,MFC說(shuō)臨時(shí)的map可以被鎖定,先記住就可以。

看一下黃色下面的代碼:

       CHandleMap* m_pmapHWND;

       CHandleMap* m_pmapHMENU;

       CHandleMap* m_pmapHDC;

       CHandleMap* m_pmapHGDIOBJ;

       CHandleMap* m_pmapHIMAGELIST;

很明顯,這里放了一些臨時(shí)的映射,包括HWND到CWnd,HDC到CDC的,等等。

并且,MFC除了這些臨時(shí)的映射表之外,還有永久的映射表。

也就是說(shuō),GetDlgItem以及FromHandle等函數(shù)返回的CWnd以及CDC等指針是可以保存的,不管是臨時(shí)的map還是永久map中的,我們都可以安全的保存,前提是把臨時(shí)的map鎖定,那么不管怎么樣,返回的指針可以在任何時(shí)候都是安全的。默認(rèn)的,MFC是在空閑時(shí)間里把臨時(shí)map里的東西清空掉的。


 


剛才說(shuō)到在空閑時(shí)間MFC會(huì)把臨時(shí)的map刪除掉,我們?cè)趧偛拍莻€(gè)按鈕事件里添上如下代碼:

AfxGetApp()->OnIdle(1);


 


然后運(yùn)行并跟蹤到如下函數(shù):

BOOL CWinApp::OnIdle(LONG lCount)

{

       if (lCount <= 0)

       {

              CWinThread::OnIdle(lCount);


 


              // call doc-template idle hook

              POSITION pos = NULL;

              if (m_pDocManager != NULL)

                     pos = m_pDocManager->GetFirstDocTemplatePosition();


 


              while (pos != NULL)

              {

                     CDocTemplate* pTemplate = m_pDocManager->GetNextDocTemplate(pos);

                     ASSERT_KINDOF(CDocTemplate, pTemplate);

                     pTemplate->OnIdle();

              }

       }

       else if (lCount == 1)

       {

              VERIFY(!CWinThread::OnIdle(lCount));

       }

       return lCount < 1;  // more to do if lCount < 1

}


 


再跟蹤進(jìn)上面的紅色函數(shù)中,整個(gè)函數(shù)如下:

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

}


 


怎么樣,當(dāng)了老半天的間諜了,總算能看出點(diǎn)門(mén)道了吧?上面3行紅色的代碼說(shuō)的很清楚,這里會(huì)把臨時(shí)的map釋放掉。

兩個(gè)函數(shù)的代碼如下:

AfxLockTempMaps();

AfxUnlockTempMaps();


 


void AFXAPI AfxLockTempMaps()

{

       AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

       ++pState->m_nTempMapLock;

}


 


BOOL AFXAPI AfxUnlockTempMaps(BOOL bDeleteTemps)

{

       AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

       if (pState->m_nTempMapLock != 0 && --pState->m_nTempMapLock == 0)

       {

              if (bDeleteTemps)

              {

                     if (bDeleteTemps != -1)

                     {

                            // allow COM libraries to be freed

                            CWinThread* pThread = AfxGetThread();

                            if (pThread != NULL && pThread->m_lpfnOleTermOrFreeLib != NULL)

                                   (*pThread->m_lpfnOleTermOrFreeLib)(FALSE, FALSE);

                     }


 


                     // clean up temp objects

 

                     pState->m_pmapHGDIOBJ->DeleteTemp();

 

                     pState->m_pmapHDC->DeleteTemp();

 

                     pState->m_pmapHMENU->DeleteTemp();

 

                     pState->m_pmapHWND->DeleteTemp();

 

                     pState->m_pmapHIMAGELIST->DeleteTemp();

              }


 


#ifndef _AFX_PORTABLE

              CWinApp* pApp = AfxGetApp();

              _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();

              // restore safety pool after temp objects destroyed

              if (pApp != NULL &&

                      (pThreadState->m_pSafetyPoolBuffer == NULL ||

                      _msize(pThreadState->m_pSafetyPoolBuffer) < pApp->m_nSafetyPoolSize) &&

                     pApp->m_nSafetyPoolSize != 0)

              {

                     // attempt to restore the safety pool to its max size

                     size_t nOldSize = 0;

                     if (pThreadState->m_pSafetyPoolBuffer != NULL)

                     {

                            nOldSize = _msize(pThreadState->m_pSafetyPoolBuffer);

                            free(pThreadState->m_pSafetyPoolBuffer);

                     }


 


                     // undo handler trap for the following allocation

                     BOOL bEnable = AfxEnableMemoryTracking(FALSE);

                     pThreadState->m_pSafetyPoolBuffer = malloc(pApp->m_nSafetyPoolSize);

                     if (pThreadState->m_pSafetyPoolBuffer == NULL)

                     {

                            TRACE1("Warning: failed to reclaim %d bytes for memory safety pool.\n",

                                   pApp->m_nSafetyPoolSize);

                            // at least get the old buffer back

                            if (nOldSize != 0)

                            {

                                   //get it back

                                   pThreadState->m_pSafetyPoolBuffer = malloc(nOldSize);

                                   ASSERT(pThreadState->m_pSafetyPoolBuffer != NULL);

                            }

                     }

                     AfxEnableMemoryTracking(bEnable);

              }

#endif  // !_AFX_PORTABLE

       }


 


       // return TRUE if temp maps still locked

       return pState->m_nTempMapLock != 0;

}


 


看到上面黃色的代碼了吧,這時(shí)候你還敢保存GetDlgItem或者FromHandle返回的指針嗎?

剛才你不是說(shuō)可以鎖定臨時(shí)map的嗎?是的,可以用AfxLockTempMaps鎖定,但是必須與AfxUnlockTempMaps配對(duì)使用,其內(nèi)部有一個(gè)計(jì)數(shù)變量。MSDN上沒(méi)這個(gè)函數(shù),最好不要用它,否則除了什么問(wèn)題我可不保證哦 J


 


永久的map存放的應(yīng)該就是我們顯示創(chuàng)建的例如CWnd此類(lèi)的對(duì)象了。

其實(shí)很多函數(shù)如FromHandle、FindWindow等函數(shù)都是用到了這種技術(shù),所以MSDN必定有這樣類(lèi)似這樣的一句話:The returned pointer may be temporary and should not be stored for later use.


 


有興趣大家自己跟蹤代碼,源碼面前了無(wú)秘密

                                                

                                                 溫柔的毒藥           2005-06-21

 

本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
CFormView
PreTranslateMessage使用與使用說(shuō)明
PreTranslateMessage作用和使用方法
MFC如何在線程中實(shí)時(shí)刷新界面
安全獲取窗口GetSafeHwnd詳細(xì)解說(shuō)
第十二章 對(duì)話框和對(duì)話框類(lèi)CDialog
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服