zoukankan      html  css  js  c++  java
  • 解析 MFC 中的 FromHandle

    MFC 对 Windows API 进行了封装,在很多方面都会提供便利。用 FromHandle 返回零时对象的指针,就可以调用各种类的方法。临时对象会在 OnIdle 中销毁。这里对 FromHandle 的实现原理从源码上进行解析。

    // 
    // 1 
    // 
    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; 
    }
    这是 CWnd 的 FromHandle 方法,大致的意思为从 CHandleMap 中获取临时 CWnd 对象的指针。
    // 
    // 2 
    // 
    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; 
    }
    再看
    #define offsetof(s,m)   (size_t)&(((s *)0)->m)
    继续
    // 
    // 3 
    // 
    CObject* CHandleMap::FromHandle(HANDLE h) 
    { 
        ASSERT(m_pClass != NULL); 
        ASSERT(m_nHandles == 1 || m_nHandles == 2);
        if (h == NULL) 
            return NULL;
        CObject* pObject = LookupPermanent(h); 
        if (pObject != NULL) 
            return pObject;   // return permanent one 
        else if ((pObject = LookupTemporary(h)) != NULL) 
        { 
            HANDLE* ph = (HANDLE*)((BYTE*)pObject + m_nOffset); 
            ASSERT(ph[0] == h || ph[0] == NULL); 
            ph[0] = h; 
            if (m_nHandles == 2) 
            { 
                ASSERT(ph[1] == h || ph[1] == NULL); 
                ph[1] = h; 
            } 
            return pObject;   // return current temporary one 
        }
        // This handle wasn't created by us, so we must create a temporary 
        // C++ object to wrap it.  We don't want the user to see this memory 
        // allocation, so we turn tracing off.
        BOOL bEnable = AfxEnableMemoryTracking(FALSE); 
    #ifndef _AFX_PORTABLE 
        _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler); 
    #endif
        CObject* pTemp = NULL; 
        TRY 
        { 
            pTemp = m_pClass->CreateObject(); 
            if (pTemp == NULL) 
                AfxThrowMemoryException();
            m_temporaryMap.SetAt((LPVOID)h, pTemp); 
        } 
        CATCH_ALL(e) 
        { 
    #ifndef _AFX_PORTABLE 
            AfxSetNewHandler(pnhOldHandler); 
    #endif 
            AfxEnableMemoryTracking(bEnable); 
            THROW_LAST(); 
        } 
        END_CATCH_ALL
    #ifndef _AFX_PORTABLE 
        AfxSetNewHandler(pnhOldHandler); 
    #endif 
        AfxEnableMemoryTracking(bEnable);
        // now set the handle in the object 
        HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);  // after CObject 
        ph[0] = h; 
        if (m_nHandles == 2) 
            ph[1] = h;
        return pTemp; 
    }
  • 相关阅读:
    HDU1698(线段树入门题)
    POJ2528(离散化+线段树区间更新)
    POJ3630(Trie树)
    HDU1251(字典树)
    HDU1247(经典字典树)
    POJ2513(字典树+图的连通性判断)
    POJ1363
    UVa11624(逃离火焰问题)
    HDOJ1495(倒水BFS)
    poj3414Pots(倒水BFS)
  • 原文地址:https://www.cnblogs.com/xingrun/p/3409541.html
Copyright © 2011-2022 走看看