如何使用动态链接库中的资源

近来在论坛上很有多帖子问到如何使用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还是不能少的。

时间: 2024-10-22 22:29:35

如何使用动态链接库中的资源的相关文章

访问动态链接库中的C++类和资源

面我们来介绍如何访问动态链接库中的C++类和资源.其具体操作步骤如下:(1)创建一个基于对话框的工程,工程名称为"AccessDll".设计对话框资源如图1所示. 图1  对话框资源设计窗口(2)定义一个名称为CTextDlg的抽象类,因为需要访问动态链接库中的CTextDlg类,因此客户端需要定义一个框架,即抽象类CTextDlg.class CTextDlg             //定义抽象类CTextDlg{public: virtual void __stdcall Sho

如何使用DLL中的资源

长久以来,把界面的信息单独存为一个DLL一直是很多商业软件的作法,比如VC.InstallShield等等,这样做的好处是,如果要做多语言版本,只要写出不同的DLL来,在主程序中使用时调用不同的DLL就行,当然现在还有一种流行的方法是使用INI,读存也非常方便.最近在网上转了转,发现竟没有一篇关于如何读取DLL中资源的文章,虽然Iczelion的Win32ASM教程中第26课"Splash Screen"讲到了读取DLL中的图片,但不知是这种问题太简单了还是其它什么原因,Iczelio

在DLL中使用资源

现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题.这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题. 1.Win32 DLL 在Win32 DLL中使用对话框很简单,你只需要在你的DLL中添加对话框资源,而且可以在对话框上面设置你所需要的控件.然后使用DialogBox或者CreateDialog这两个函数(或相同作用的其它函数)来创建对话框,并定义你自己的对话框回调函数处理对话框收到的消息.下面通过一个具体实例

在Applet中引用jar中的资源文件的方法

如果想要做一个比较漂亮的Applet让人家使用,一定会加上很多资源,比如图片或者声音文件什么的. sun提供了一个有用的工具,jar.这个工具可以把这些资源文件合在一个文件里,避免频繁的http request, 而且下载的jar文件可以被缓存,很爽吧. 但是如何正确引用jar中的资源呢? 比如我们打算显示一个图片按钮,图片相对路径为./img/logo.gif,你可以自己随便找一个gif图片. 让我们来看看我们想当然的做法. import java.awt.*; import java.awt

qt-Qt 中添加资源文件到qrc中,文件过多过大时该怎么办?

问题描述 Qt 中添加资源文件到qrc中,文件过多过大时该怎么办? 这些文件不想暴露在程序目录中,有没有设么方法让这些资源全部编译进exe中?或者当文件过多过大时仍可以继续添加进qrc?还有qrc添加的资源文件的上限是怎么样的? 解决方案 貌似可以在工程PRO文件中,添加: CONFIG += resources_big 解决方案二: qt中添加资源文件qt资源文件Qt中的qrc文件 解决方案三: 有没有大神过来解答下啊!!!! 解决方案四: 你可以把资源文件先加密,然后程序中解密到内存中,然后

vc++编程问题-VC中自定义资源的读取

问题描述 VC中自定义资源的读取 自定义资源LOADRESOURCE之后,返回的是HGLOBAL 类型,因为我要分析这个文件,提取有用信息,所以一直用fread fseek fopen 操作,但是类型不符,fread的参数都是FILE类型的,这该怎么办?

过滤Android工程中多余资源文件的解决方法_Android

本文以实例讲述了过滤Android工程中多余资源文件的解决方法,很有实用价值!具体描述如下: 很多开发人员在Android项目开发过程中经常会遇到这样的情况:界面开发人员发布了一个新版本的资源包,不过有的图片名称改了,有的图片删掉了,可是在实现的时候开发人员只是把新的资源覆盖到原来的资源文件夹中,随着版本的发布,在drawable或values中积累的无用资源越来越多,直到最后发布正式版的时候再想要删除这些多余的文件,于是不得不一个一个文件检查看是否有用,再决定要不要删除之. 有鉴于此,很有必要

在Android开发中替换资源图片不起作用的解决方法_Android

现象 在android开发中,经常会需要替换res\drawable中的图片,打开res\layout下的文件预览布局页面发现图片已经被替换,但在模拟器或者真实机器上运行时发现该图片并没有被替换,还是使用的是原来的资源图片. 原因 在开发过程中,由于使用模拟器测试了程序,在首次运行后会将res文件夹下的图片资源文件(如drawable-hdpi.drawable-ldpi和drawable-mdpi)拷贝到bin文件夹下.在替换资源图片后,eclipse并不清楚是否有图片改变,所以会使用原来bi

javaweb中的资源上传与下载

问题描述 javaweb中的资源上传与下载 求一份关于javaweb中的资源上传与下载的模块代码,,,,,,,,,,,,, 解决方案 这个是上传的代码 package demo; import java.io.File; import org.apache.commons.io.FileUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; publi