且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

DLL 支持MFC 没有DLLMAIN函数

更新时间:2022-09-06 23:14:38

如果使用VC编写DLL时,需要MFC功能; 一般在源文件里就不能手动写DLLMAIN函数了

它给MFC集成了,\src\mfc\dllmodule.cpp
打开它,里面有有一个DLLMAIN函数,根据源码意思就可以看出来,

这里截取的一点点代码
if (dwReason == DLL_PROCESS_ATTACH)
    {
        BOOL bResult = FALSE;

#ifdef _AFXDLL
        // wire up resources from core DLL
        AfxCoreInitModule();
#endif

        _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
        }

        // initialize the single instance DLL
        CWinApp* pApp; pApp = AfxGetApp();////关键在这里了
        if (pApp != NULL && !pApp->InitInstance())///这里会调用 初始化函数
        {
            pApp->ExitInstance();///这也是退出时函数
            AfxWinTerm();
            goto Cleanup;       // Init Failed
        }

        pState->m_pPrevModuleState = pPrevModState;
#ifdef _AFXDLL
        // wire up this DLL into the resource chain
        VERIFY(AfxInitExtensionModule(controlDLL, hInstance));
        TRY
        {
            CDynLinkLibrary* pDLL; 
            pDLL = new CDynLinkLibrary(controlDLL);
        }
        CATCH(CMemoryException, e)
        {
            DELETE_EXCEPTION(e);
            pApp->ExitInstance();
            AfxWinTerm();
            goto Cleanup;       // Init Failed
        }
        END_CATCH



DLL_PROCESS_ATTACH

DLL_PROCESS_DETACH

这是莪们关心的,从上面代码中可以看到,这里面MFC调用一个全局的CWinApp类的 初始化函数


也就是说,现在写一个类,让它继承CWinApp

然后重载它的InitInstace 和ExitInstace就可以了

在InitInstace时里面写入所需要的代码就可以了

然后在声明一个全局的变量,一定要是个全局变量

当然这个类可以不用做任何事情,就提供初始化和退出时处理的函数



如果在DLL 动态库中导出全局变量
extern int __decspec


如果EXE中要使用DLL中的资源,因为DLL和EXE的资源ID很有可能会冲突,在函数第一行加入如下代码可解决此问题

AFX_MANAGE_STATE(AfxGetStaticModuleState());

AFX_MANAGE_STATE是一个宏,其原型为: 

AFX_MANAGE_STATE( AFX_MODULE_STATE* pModuleState )


该宏用于将pModuleState设置为当前的有效模块状态。当离开该宏的作用域时(也就离开了pModuleState所指向栈上对象的作用域),先前的模块状态将由AFX_MODULE_STATE的析构函数恢复。

方法二 在DLL接口函数中使用:

AfxGetResourceHandle();

AfxSetResourceHandle(HINSTANCE xxx);


AfxGetResourceHandle用于获取当前资源模块句柄,而AfxSetResourceHandle则用于设置程序目前要使用的资源模块句柄。

我们将DLL中的接口函数ShowDlg改为:
void ShowDlg(void)

{ 

//方法2的状态变更

HINSTANCE save_hInstance = AfxGetResourceHandle(); 

AfxSetResourceHandle(theApp.m_hInstance); 



CDialog dlg(IDD_DLL_DIALOG);//打开ID为2000的对话框

dlg.DoModal();

//方法2的状态还原

AfxSetResourceHandle(save_hInstance);