<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    深入解析MFC -- 句柄與對象的關系

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    CWnd::FromHandlePermanent ——根據窗口句柄得到CWnd*指針

    This function, unlike FromHandle, does not create temporary objects.

     

    CWnd::FromHandle——根據窗口句柄得到CWnd*指針

    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* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
    {
     CHandleMap* pMap = afxMapHWND();  //即,afxMapHWND(FALSE);  
     CWnd* pWnd = NULL;
     if (pMap != NULL)
     {
      // only look in the permanent map - does no allocations
      pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
      ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
     }
     return pWnd;
    }

     

     

    在Windows體系中,很多對象都是以句柄的形式展示給開發人員的。比如窗口句柄(HWND),繪圖設備(HDC)等等。然后大部分的API函數則圍繞 這些句柄做文章。比如ShowWindow,SetWindowText,TextOut等等。這些API函數的第一個參數通常就是句柄了。但是在C++ 體系中,這種對于事物細節的訪問,往往是有違其封裝精神的。因此MFC做了很多的封裝類,來隱藏這些細節。應運而生就是CWnd,CDC等類。通過這些類 暴露的方法,可以直接對句柄做操作,而又可以不去關心他。
    不過,我們今天的主題不在這里。以下才是真正的內容。
    按照C++的理論,被封裝的句柄的創建和銷毀都應該由類本身來完成,外界不了解其中細節。但是在MFC中,真是這樣嗎?至少CWnd不是這樣,HWND并 不完全在CWnd的掌控之中。在前一章我提到過,MFC中有大量的全局變量,其中一個全局變量是一張HWND與CWnd的Map表。這個Map表的位置不 好找,上章提到過全局對象AFX_MODULE_STATE,他其中有一個成員的類型是AFX_MODULE_THREAD_STATE,在 AFX_MODULE_THREAD_STATE的內部,則有著一群Map表,m_pmapHWND正是其中一個:

    CHandleMap m_pmapHWND;
    CHandleMap* m_pmapHMENU;
    CHandleMap* m_pmapHDC;
    CHandleMap* m_pmapHGDIOBJ;
    CHandleMap* m_pmapHIMAGELIST;
    看到了嗎?找起來是比較麻煩,不過MFC提供了全局函數afxMapHWND,無論在哪個地方,調用這個函數都能輕松的獲得這個Map表。
    那么,這個表到底有什么作用呢?其實非常簡單,雖然在MFC中,都是對象在與對象打交道。但是MFC也要與Windows系統打交道。Windows給你的只有句柄,那么如何通過這些句柄找到相對應的類呢?通過Map表就能輕松的解決這個問題。
    比如在Windows的消息機制中,當WndProc接收到一個消息的時候,只會得到一個HWND hWnd的目標窗口,如何找到匹配的類?從m_pmapHWND中搜索就行了。通過調用CWnd的靜態成員函數FromHandlePermanent,我們就能輕松的從Map表中找到與hWnd相對應的CWnd類。
    FromHandlePermanent的實現也非常簡單。首先通過afxMapHWND找到m_pmapHWND,然后通過m_pmapHWND的成員函數LookupPermanent查找與hWnd對應的CWnd指針,最后返回他。
    m_pmapHWND是什么時候被創建的呢?在第一個窗口被創建出來的時候,會調用CWnd的Attach函數,下面是具體的函數實現:
    BOOL CWnd::Attach(HWND hWndNew)
    {
    if (hWndNew == NULL) return FALSE;
    CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist
    pMap->SetPermanent(m_hWnd = hWndNew, this);
    return TRUE;
    }
    注意調用afxMapHWND的傳入的參數為TRUE,這表示當Map不存在時,則創建他。再讓我們看看afxMapHWND的實現:
    CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
    {
    AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
    if (pState->m_pmapHWND == NULL && bCreate)
    {
     pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CWnd),
      ConstructDestruct<CWnd>::Construct, ConstructDestruct<CWnd>::Destruct,
      offsetof(CWnd, m_hWnd));
    }
    return pState->m_pmapHWND;
    }
    afxMapHWND首先從我們前面說的地方找到這個指針,如果指針為空,并且bCreate為TRUE,則創建一個新的CHandleMap。非常簡單,不是嗎?RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全