<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>
  • 網站首頁 > 物聯資訊 > 技術分享

    如何使用動態鏈接庫中的資源

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

    近來在論壇上很有多帖子問到如何使用DLL中的資源(包括對話框,圖標等)的問題,現在筆者就來就此問題談談,包含在DLL內部使用資源,DLL中使用其它DLL中的資源和在應用程序中使用資源。

           我們先以圖標為例說起(其它的資源與此圖標的加載原理大致相同),我們要加載圖標,一般是調用AfxGetApp()->LoadIcon(…);下面是CWinApp::LoadIcon的實現(afxwin2.inl):

    _AFXWIN_INLINE HICON CWinApp::LoadIcon(LPCTSTR lpszResourceName) const

    { return ::LoadIcon(AfxFindResourceHandle(lpszResourceName,

             RT_GROUP_ICON), lpszResourceName); }

    _AFXWIN_INLINE HICON CWinApp::LoadIcon(UINT nIDResource) const

    { return ::LoadIcon(AfxFindResourceHandle(MAKEINTRESOURCE(nIDResource),

             RT_GROUP_ICON), MAKEINTRESOURCE(nIDResource)); }

           可以看到CWinApp::LoadIcon實際上調用了API .LoadIcon,下面是API LoadIcon的原型:

    HICON LoadIcon(      
     
        HINSTANCE hInstance,
        LPCTSTR lpIconName
    );

     

    hInstance

    [in] Handle to an instance of the module whose executable file contains the icon to be loaded. This parameter must be NULL when a standard icon is being loaded.

    hInstance是我們要加載ICON的模塊實例,這個實例從何來,當然我們可以直接傳入DLL的實例,對于通過LoadLibrary動態加載的DLL我們可以很容易的得到其句柄,但對于我們直接鏈接的DLL得到其句柄則要費一番周折。可以看到CWinApp::LoadIcon是通過AfxFindResouceHandle找到此句柄的。下面是AfxFindResourceHandle的定義(afxwin.h):

    #ifndef _AFXDLL

    #define AfxFindResourceHandle(lpszResource, lpszType) AfxGetResourceHandle()

    #else

    HINSTANCE AFXAPI AfxFindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType);

    #endif

           我們先討論在靜態鏈接庫中使用MFC DLL的情況。可以看到,我們如果在靜態庫中使用MFC DLL的話(#ifndef _AFXDLL),實際上就是調用的AfxGetResourceHandle,MSDN中的說明是

    AfxGetResourceHandle  

    This function accesses the application’s resources directly by using the HINSTANCE handle returned, for example, in calls to the Windows function FindResource.

    HINSTANCE AfxGetResourceHandle( );

    Return Value

    An HINSTANCE handle where the default resources of the application are loaded.

    函數返回的應用程序加載的缺省資源的HINSTANCE句柄,HINSTANCE相當于HMODULE,也就是資源所在的模塊句柄。顯然在此,我們使用的是DLL中的資源,那么我們就應該返回此DLL中的HINSTANCE了,如果讓AfxGetResourceHandle返回DLL的HINSTANCE呢?答案是通過AfxSetResourceHandle設置。MSDN中AfxSetResouceHandle的說明如下:

    AfxSetResourceHandle

    This function sets the HINSTANCE handle that determines where the default resources of the application are loaded.

    void AfxSetResourceHandle(

    HINSTANCE hInstResource );

    Parameters

    hInstResource

    Specifies the instance or module handle to an .EXE or DLL file from which the application’s resources are loaded.

    我們只需將DLL的HINSTANCE傳入AfxSetResouceHanle就行了。如何得到DLL的HINSTANCE呢,我們可以通過DLL聲明一個接口HINSTANCE GetInstance獲得,也可以通過EnumProcessMoudules找到(詳細的過程見MSDN中EnumProcessModules的說明和示例)。

    我們使用完DLL中的資源要使用EXE中的資源的資源怎么辦呢?我們需要在使用完成后用AfxSetResource重新將資源模塊的句柄設置為原來的值,如果來保證在資源使用完成后完成這一個工作呢,即使在使用過程中發生異常了,為此我們利C++類的構造和析構機制創建了這一類:

    class CLocalResource 

    {

    public:

             CLocalResource(HINSTANCE hInstance)

    {

             m_hInstOld=AfxGetInstanceHandle();

             AfxSetInstanceHandle(hInstance);

    }

             virtual ~CLocalResource()

    {

             AfxSetInstanceHandle(m_hInstOld);

    }

    protected:

             HINSTANCE m_hInstOld;

    };

             我們只需在使用DLL的資源之前構造一個CLocalInstance就行了。

    void CXXXX::LoadResouceFromDLL(HINSTANCE hInst,UINT nResID,…)

    {

             CLocalResouce localRes(hInst);

             …

    }

    下面來討論在動態庫中使用MFC DLL的情況(也就是定義了_AFXDLL的情況)

    來看看AfxGetInstanceHandle ,AfxGetResourceHandle和AfxSetResouceHandle的實現(afxwin1.inl中):

    _AFXWIN_INLINE HINSTANCE AFXAPI AfxGetInstanceHandle()

             { ASSERT(afxCurrentInstanceHandle != NULL);

             return afxCurrentInstanceHandle; }

    _AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle()

    { ASSERT(afxCurrentResourceHandle != NULL);

    return afxCurrentResourceHandle; }

    _AFXWIN_INLINE void AFXAPI AfxSetResourceHandle(HINSTANCE hInstResource)

    { ASSERT(hInstResource != NULL); afxCurrentResourceHandle = hInstResource; }

    實際上訪問的就是afxCurrentInstanceHandle,afxCurrentResourceHandle。

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

    // Global functions for access to the one and only CWinApp

    #define afxCurrentInstanceHandle    AfxGetModuleState()->m_hCurrentInstanceHandle

    #define afxCurrentResourceHandle   AfxGetModuleState()->m_hCurrentResourceHandle

    ….

    AFX_MODULE_STATE* AFXAPI AfxGetModuleState()

    {

             _AFX_THREAD_STATE* pState = _afxThreadState;

             AFX_MODULE_STATE* pResult;

             if (pState->m_pModuleState != NULL)

             {

                       // thread state's module state serves as override

                       pResult = pState->m_pModuleState;

             }

             else

             {

                       // otherwise, use global app state

                       pResult = _afxBaseModuleState.GetData();

             }

             ASSERT(pResult != NULL);

             return pResult;

    }

    其中的_AFX_THREAD_STATE在此我們就不討論了,有興趣的讀者可以閱讀(afxstat_.h和afxstate.cpp)。

             那AfxGetModuleState()->m_hCurrentResourceHandle又是在哪初始化的呢?

    我們可以在appinit.cpp中的BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)看到

    // set resource handles

             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

             pModuleState->m_hCurrentInstanceHandle = hInstance;

             pModuleState->m_hCurrentResourceHandle = hInstance;

           和appinit.cpp中的void CWinApp::SetCurrentHandles()中看到

             AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();

             pModuleState->m_hCurrentInstanceHandle = m_hInstance;

             pModuleState->m_hCurrentResourceHandle = m_hInstance;

             CWinApp::SetCurrentHandles()也是由AfxWinInit調用的,那AfxWinInit又由誰調用呢?

    我們可以在DllMain(dllinit.cpp和dllmodul.cpp,分別對應于MFC擴展DLL和MFC規則DLL)看到

    (dllinit.cpp,MFC擴展DLL)

    static AFX_EXTENSION_MODULE coreDLL;

    ….

    extern "C"

    BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)

    {

             if (dwReason == DLL_PROCESS_ATTACH)

             {

                       …….

                       // initialize this DLL's extension module

                       VERIFY(AfxInitExtensionModule(coreDLL, hInstance));

    #ifdef _AFX_OLE_IMPL

                       AfxWinInit(hInstance, NULL, _T(""), 0);

     

                       ….

    #endif

    ….

                       // wire up this DLL into the resource chain

                       CDynLinkLibrary* pDLL = new CDynLinkLibrary(coreDLL, TRUE);

                       ASSERT(pDLL != NULL);

                       pDLL->m_factoryList.m_pHead = NULL;

                       ….

             }

             else if (dwReason == DLL_PROCESS_DETACH)

             {

                       ….

                       // cleanup module state for this process

                       AfxTermExtensionModule(coreDLL);

                       ….

                       // cleanup module state in OLE private module state

                       AfxTermExtensionModule(coreDLL, TRUE);

                       ….

             }

             …

    }

    可以看到在提供自動化支持時,將調用AfxWinInit(但MFC的DLL向導,對于擴展DLL卻不允許添加自動化支持)。

    (在dllmodul.cpp中,MFC常規DLL)

    #ifdef _AFXDLL

    static AFX_EXTENSION_MODULE controlDLL;

    ….

    #endif

     

    extern "C"

    BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)

    {

             if (dwReason == DLL_PROCESS_ATTACH)

             {

    ….

                       _AFX_THREAD_STATE* pState = AfxGetThreadState();

                       AFX_MODULE_STATE* pPrevModState = pState->m_pPrevModuleState;

     

                       // Initialize DLL's instance(/module) not the app's

                       if (!AfxWinInit(hInstance, NULL, _T(""), 0))

                       {

                                AfxWinTerm();

                                goto Cleanup;       // Init Failed

                       }

     

                       ….

    #ifdef _AFXDLL

                       // wire up this DLL into the resource chain

                       VERIFY(AfxInitExtensionModule(controlDLL, hInstance));

                       CDynLinkLibrary* pDLL; pDLL = new CDynLinkLibrary(controlDLL);

                       ASSERT(pDLL != NULL);

    #else

                       AfxInitLocalData(hInstance);

    #endif

             }

             else if (dwReason == DLL_PROCESS_DETACH)

             {

    ….

    #ifdef _AFXDLL

                       AfxTermExtensionModule(controlDLL, TRUE);

    #else

                       AfxTermLocalData(hInstance, TRUE);

    #endif

             }

             …

    }

             看到上面的代碼,其實與MFC擴展DLL的代碼大同小異,只過是MFC常規DLL可以支持在靜態鏈接庫全用MFC DLL,相應的初始化/反初始化函數就變為了AfxInitLocalData/ AfxTermLocalData,在此我們不對在靜態鏈接庫中使用MFC DLL的情況作更多討論。

    以及在winmain.cpp中的int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow),在appmodul.cpp中我們可以看到入口函數的實現:

    extern "C" int WINAPI

    _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

             LPTSTR lpCmdLine, int nCmdShow)

    {

             // call shared/exported WinMain

             return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

    }

    看看AfxInitExtensionModule , AfxTermExtensionModule CDynLinkLibrary的定義(afxdll_.h)和實現(在dllinit.cpp中)就明白了DllMain做了什么:

     

    BOOL AFXAPI AfxInitExtensionModule(AFX_EXTENSION_MODULE& state, HMODULE hModule)

    {

             // only initialize once

             if (state.bInitialized)

             {

                       AfxInitLocalData(hModule);

                       return TRUE;

             }

             state.bInitialized = TRUE;

             // save the current HMODULE information for resource loading

             ASSERT(hModule != NULL);

             state.hModule = hModule;

             state.hResource = hModule;

             // save the start of the runtime class list

             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

             state.pFirstSharedClass = pModuleState->m_classList.GetHead();

             pModuleState->m_classList.m_pHead = pModuleState->m_pClassInit;

     

    #ifndef _AFX_NO_OLE_SUPPORT

             // save the start of the class factory list

             state.pFirstSharedFactory = pModuleState->m_factoryList.GetHead();

             pModuleState->m_factoryList.m_pHead = pModuleState->m_pFactoryInit;

    #endif

             return TRUE;

    }

    void AFXAPI AfxTermExtensionModule(AFX_EXTENSION_MODULE& state, BOOL bAll)

    {

             // make sure initialized

             if (!state.bInitialized)

                       return;

     

             // search for CDynLinkLibrary matching state.hModule and delete it

             ASSERT(state.hModule != NULL);

             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

             AfxLockGlobals(CRIT_DYNLINKLIST);

             for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL; )

             {

                       CDynLinkLibrary* pNextDLL = pDLL->m_pNextDLL;

                       if (bAll || pDLL->m_hModule == state.hModule)

                                delete pDLL;    // will unwire itself

                       pDLL = pNextDLL;

             }

             AfxUnlockGlobals(CRIT_DYNLINKLIST);

             // delete any local storage attached to this module

             AfxTermLocalData(state.hModule, TRUE);

             // remove any entries from the CWnd message map cache

             AfxResetMsgCache();

    }

     

    class CDynLinkLibrary : public CCmdTarget

    {

             DECLARE_DYNAMIC(CDynLinkLibrary)

    public:

     

    // Constructor

             explicit CDynLinkLibrary(AFX_EXTENSION_MODULE& state, BOOL bSystem = FALSE);

             CDynLinkLibrary(HINSTANCE hModule, HINSTANCE hResource);

     

    // Attributes

             HMODULE m_hModule;

             HMODULE m_hResource;                // for shared resources

             ….

             BOOL m_bSystem;                     // TRUE only for MFC DLLs

    // Implementation

    public:

             CDynLinkLibrary* m_pNextDLL;        // simple singly linked list

             virtual ~CDynLinkLibrary();

    ….

    };

     

    CDynLinkLibrary::CDynLinkLibrary(AFX_EXTENSION_MODULE& state, BOOL bSystem)

    {

             // copy info from AFX_EXTENSION_MODULE struct

             ASSERT(state.hModule != NULL);

             m_hModule = state.hModule;

             m_hResource = state.hResource;

             m_classList.m_pHead = state.pFirstSharedClass;

    ….

             m_bSystem = bSystem;

            

    // insert at the head of the list (extensions will go in front of core DLL)

             DEBUG_ONLY(m_pNextDLL = NULL);

             AfxLockGlobals(CRIT_DYNLINKLIST);

             m_pModuleState->m_libraryList.AddHead(this);

             AfxUnlockGlobals(CRIT_DYNLINKLIST);

    }

     

    CDynLinkLibrary::CDynLinkLibrary(HINSTANCE hModule, HINSTANCE hResource)

    {

             m_hModule = hModule;

             m_hResource = hResource;

             m_classList.m_pHead = NULL;

             …

             m_bSystem = FALSE;

             // insert at the head of the list (extensions will go in front of core DLL)

             DEBUG_ONLY(m_pNextDLL = NULL);

             AfxLockGlobals(CRIT_DYNLINKLIST);

             m_pModuleState->m_libraryList.AddHead(this);

             AfxUnlockGlobals(CRIT_DYNLINKLIST);

    }

    CDynLinkLibrary::~CDynLinkLibrary()

    {

             // remove this frame window from the list of frame windows

             AfxLockGlobals(CRIT_DYNLINKLIST);

             m_pModuleState->m_libraryList.Remove(this);

             AfxUnlockGlobals(CRIT_DYNLINKLIST);

    }

           由此我們可以看出DLL初始化時先調AfxInitExtensionModule是為了構造一個AFX_EXTENSION_MODULE,然后將它插入插入一個AFX_MODULE_STATE鏈表中,同時將當前DLL的HINSTANCE插入此AFX_MODULE_STATE的CDynLinkLibrary鏈表中,以便稍后講到的AfxFindResourceHandle找到。DLL從內存移出時就從此鏈表中刪除自己。

    讓我們來看看AfxFindResourceHandle的實現(dllinit.cpp):

    HINSTANCE AFXAPI AfxFindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType)

    {

             ASSERT(lpszName != NULL);

             ASSERT(lpszType != NULL);

     

             HINSTANCE hInst;

     

             // first check the main module state

             AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

             if (!pModuleState->m_bSystem)

             {

                       hInst = AfxGetResourceHandle();

                       if (::FindResource(hInst, lpszName, lpszType) != NULL)

                                return hInst;

             }

     

             // check for non-system DLLs in proper order

             AfxLockGlobals(CRIT_DYNLINKLIST);

             CDynLinkLibrary* pDLL;

             for (pDLL = pModuleState->m_libraryList; pDLL != NULL;

                       pDLL = pDLL->m_pNextDLL)

             {

                       if (!pDLL->m_bSystem && pDLL->m_hResource != NULL &&

                                ::FindResource(pDLL->m_hResource, lpszName, lpszType) != NULL)

                       {

                                // found it in a DLL

                                AfxUnlockGlobals(CRIT_DYNLINKLIST);

                                return pDLL->m_hResource;

                       }

             }

             AfxUnlockGlobals(CRIT_DYNLINKLIST);

     

             // check language specific resource next

             hInst = pModuleState->m_appLangDLL;

             if (hInst != NULL && ::FindResource(hInst, lpszName, lpszType) != NULL)

                       return hInst;

     

             // check the main system module state

             if (pModuleState->m_bSystem)

             {

                       hInst = AfxGetResourceHandle();

                       if (::FindResource(hInst, lpszName, lpszType) != NULL)

                                return hInst;

             }

     

             // check for system DLLs in proper order

             AfxLockGlobals(CRIT_DYNLINKLIST);

             for (pDLL = pModuleState->m_libraryList; pDLL != NULL; pDLL = pDLL->m_pNextDLL)

             {

                       if (pDLL->m_bSystem && pDLL->m_hResource != NULL &&

                                ::FindResource(pDLL->m_hResource, lpszName, lpszType) != NULL)

                       {

                                // found it in a DLL

                                AfxUnlockGlobals(CRIT_DYNLINKLIST);

                                return pDLL->m_hResource;

                       }

             }

             AfxUnlockGlobals(CRIT_DYNLINKLIST);

     

             // if failed to find resource, return application resource

             return AfxGetResourceHandle();

    }

    上面的代碼首先檢查主模塊的狀態,通過返回的是個AFX_MODULE_STATE的類對象指針. AFX_MODULE_STATE又是個什么呢?下面看看AFX_MODULE_STATE的定義(afxstat_.h中,它的實現在afxstate.cpp中,有興趣的讀者可以讀讀):

    // AFX_MODULE_STATE (global data for a module)

    class AFX_MODULE_STATE : public CNoTrackObject

    {

    public:

    #ifdef _AFXDLL

             AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,

                       BOOL bSystem = FALSE);

    #else

             explicit AFX_MODULE_STATE(BOOL bDLL);

    #endif

             ~AFX_MODULE_STATE();

     

             CWinApp* m_pCurrentWinApp;

             HINSTANCE m_hCurrentInstanceHandle;

             HINSTANCE m_hCurrentResourceHandle;

             LPCTSTR m_lpszCurrentAppName;

             BYTE m_bDLL;    // TRUE if module is a DLL, FALSE if it is an EXE

             BYTE m_bSystem; // TRUE if module is a "system" module, FALSE if not

             …

     

    #ifdef _AFXDLL

             // CDynLinkLibrary objects (for resource chain)

             CTypedSimpleList<CDynLinkLibrary*> m_libraryList;

     

             // special case for MFC71XXX.DLL (localized MFC resources)

             HINSTANCE m_appLangDLL;

    #endif

    ….

    };

    我們來看看我們關心的屬性

    CWinApp* m_pCurrentWinApp;

    HINSTANCE m_hCurrentInstanceHandle;

    HINSTANCE m_hCurrentResourceHandle;

    LPCTSTR m_lpszCurrentAppName;

     

    BYTE m_bDLL;    // TRUE if module is a DLL, FALSE if it is an EXE

    BYTE m_bSystem; // TRUE if module is a "system" module, FALSE if not

    // CDynLinkLibrary objects (for resource chain)

    CTypedSimpleList<CDynLinkLibrary*> m_libraryList;

     

    // special case for MFC71XXX.DLL (localized MFC resources)

    HINSTANCE m_appLangDLL;

    看了相關注釋,也就明白什么意思了,在此就不多解釋了。

     

    如果當前主模塊是系統模塊(通過m_bSystem標識),并且從當前模塊中找到了相應的資源就返回此模塊的HINSTANCE。接下來當前模塊所載的DLL鏈表中的所有用戶模塊中查找,本地化的MFC資源DLL中查找,系統DLL中查找。如果都找不到則從EXE(或者通過AfxSetResouceHandle中設置的HINSTANCE)中查找。

    如果不考慮DLL鏈表,則需要我們每次使用DLL中的資源前調用AfxSetResouceHandle,使用后再調用AfxSetResourceHandle,就同前面講的在靜態鏈接庫中使用MFC DLL一樣。麻不麻煩?

    怎么解決呢?解決方法是用資源DLL的HINSTANCE構造一CDynLinkLibrary對象插入主模塊(EXE)的AFX_MODULE_STATE的m_libraryList中。怎么做?

    看了上面DllMain的實現代碼,我們可以照著做。

    static AFX_EXTENSION_MODULE ResouceDLL = { NULL, NULL }

    BOOL CXApp::InitInstance()

    {

    // Get the resource DLL instance

             if (!AfxInitExtensionModule(ResouceDLL, hResourceModule))

                      return 0;

    new CDynLinkLibrary(ResouceDLL);  

    }

    int CGenericMFCApp::ExitInstance()

    {

    AfxTermExtensionModule(ResouceDLL);

             return CWinApp::ExitInstance();

    }

    這樣我們就可以在應用程序中安全的使用DLL中的資源了,就好比EXE中的一樣。對于我們自己編寫入口函數的DLL,如果其中涉及到資源的話,我們可以參考上述的MFC常規DLL的實現。

    對于我們在ActiveX和一些DLL中的AFX_MANAGE_STATE(AfxGetStaticModuleState());我們又怎么理解呢?看看afxstat_.h:

    #ifdef _AFXDLL

    class _AFX_THREAD_STATE;

    struct AFX_MAINTAIN_STATE2

    {

             explicit AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pModuleState);

             ~AFX_MAINTAIN_STATE2();

    protected:

             AFX_MODULE_STATE* m_pPrevModuleState;

             _AFX_THREAD_STATE* m_pThreadState;

    };

    #define AFX_MANAGE_STATE(p) AFX_MAINTAIN_STATE2 _ctlState(p);

    #else  // _AFXDLL

    #define AFX_MANAGE_STATE(p)

    #endif //!_AFXDLL

     

    對于在靜態庫中使用MFC DLL時它就相當于不存在,反之,它構造一個AFX_MAINTAIN_STATE2對象,在afxstate.cpp中

    #ifdef _AFXDLL

     

    AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pNewState)

    {

             m_pThreadState = _afxThreadState;

             m_pPrevModuleState = m_pThreadState->m_pModuleState;

             m_pThreadState->m_pModuleState = pNewState;

    }

    #endif //_AFXDLL

    ,

    再看dllmodul.cpp中有關AfxGetStaticModuleState的實現:

     

    static _AFX_DLL_MODULE_STATE afxModuleState;

     

     

    AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

    {

             AFX_MODULE_STATE* pModuleState = &afxModuleState;

             return pModuleState;

    }

     

    (MFC中太多的全局變量的確不雅!)

    可以看到通過構造一個AFX_MAINTAIN_STATE2對象(再結合AfxGetResouceHandle的實現),就使AfxFindResourceHandle返回的是ActiveX控件(實際上也是一個常規DLL)或DLL的HINSTANE了,這樣AfxFindResourceHandle就不必須在DLL鏈表中查找了,但缺點是每次使用資源(或響應消息)時都要構造一個AFX_MAINTAIN_STATE2對象,并且,而且使用這種方法在此DLL中無法使用其它DLL中的資源或在EXE中使用DLL中的資源(在不使用AfxSetResourceHandle/AfxGetResourceHandle的前提下)。當然,我們這兒關心的只是資源的使用,如果涉及到其它,包括事件響應或多個UI線程時,AFX_MODULE_STATE還是不能少的。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全