我很早的时候写过一篇MFC中CDialog与其对话框资源的绑定,但这几天在MFC DLL上做了一些工作后发现当时的理解实在肤浅。说不定过了几年再回头看看目前这篇文章,又觉得本文也是鬼话连篇了吧,哈哈。

使用DLL中的资源面临的一个主要问题是,DLL和EXE中都有资源集,但是程序在运行态到底会去哪个资源集中找常常令我们疑惑。

考虑如下的经典情况:

在新建MFC DLL工程时选中Regular DLL using shared MFC DLL选项,新建一个与MFC自身DLL共享的DLL。在新DLL中新建一个ID名为IDD_DLLDIALOG的对话框资源。在这个DLL中导出一个ShowDialog()函数,内容如下:

1

extern "C" void Show Dialog()

2

{

3

CDialog dlg(IDD_DLLDIALOG);

4

dlg.DoModal();

5

}

新建一个MFC的EXE工程,导入刚刚新建的DLL工程的lib和dll,将OK按钮的响应函数设置为:  ShowDialog();  编译链接通过后,我们运行起程序来会发现点击OK按钮后什么反应都没有!怎么会这样?我们不是明明在DLL里设定好了IDD_DLLDIALOG吗?请大家注意“在新建MFC DLL工程时选中Regular DLL using shared MFC DLL”这句话,如果我们当时选的是“Regular DLL with MFC statically linked”又会是什么情况呢?又能正常显示了!

使用静态连接的方式访问MFC库DLL,会把MFC库DLL与工程本身一起打包,而共享的方式则会在运行时去系统路径中动态加载MFC库DLL。我们可以这么理解以上的现象:如果新建的DLL使用共享的方式访问库DLL,当EXE程序运行时,实际上有两套上下文系统在运作,而静态连接则只有一套上下文系统了,因此在静态连接时会需要进行模块状态的切换。

当我们新建的是共享方式访问 库DLL的DLL时,要解决上述问题比较通用的做法是在ShowDialog函数里面加上一句AFX_MANAGE_STATE(AfxGetStaticModuleState());

AfxGetStaticModuleState()的原型为:

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState( );

即当前模块的ModuleState指针。

AFX_MANAGE_STATE宏则会以传入的指针为参数去在栈上新建一个类,此类会做哪些事相信聪明的你也能猜到了.没错,它会在构造函数中存下当前的ThreadState所指向的ModuleState指针,再将传入的指针指定为当前ThreadState所指向的指针。等到这个类的实例被析构是,又将其改回去。

令外一种方法是使用AfxGetResourceHander()配合AfxSetResourceHander(HINSTANCE)了(这也正是我在MFC中CDialog与其对话框资源的绑定中介绍的方法)。

如果我们不想在EXE中通过间接的调用DLL导出的ShowDialog(),而是直接想在EXE的OnBnClickedOk()中生成一个使用DLL中对话框资源的对话框呢?这时AFX_MANAGE_STATE(AfxGetStaticModuleState())就派不上用场了(因这它是用在DLL工程中的)。最好的办法是用AfxSetResourceHander(HINSTANCE)配合GetModuleHandle(LPCTSTR)。

GetModuleHandle(LPCTSTR str)将会根据传入的字符串得到相应的模块句柄。注意,EXE和DLL都可以被看作是模块。当传入为空(NULL)时,将得到当前进程(EXE)的HINSTANCE句柄。使用GetModuleHandle要保证相应的dll已经被加载,也许你会说这个条件不是废话么,但是这确实是很容易犯错的地方。

如果是用静态加载DLL的方式(即直接把生成的那个.lib文件导入),而之前又从未调用过这个dll中的任何函数或变量的话,GetModuleHandle只会得到一个空值。因为系统会直到有某个语句调用过dll里面的东西时才会将dll真正加载。

例如:

1

void CUseDllDlg::OnBnClickedOk()

2

{

3

HINSTANCE temp = AfxGetResourceHandle();

4

AfxSetResourceHandle(GetModuleHandle(_T("RegDll")));

5

CDialog dlg(4000);

6

dlg.DoModal();

7

AfxSetResourceHandle(temp);

8

}

上面的这份代码运行时会报错,因为AfxSetResourceHandle在检查入参时发现了个空值。而下面的代码则不会有问题:

1

void CUseDllDlg::OnBnClickedOk()

2

{

3

ASSERT(TestOnly() == 1);

4

HINSTANCE temp = AfxGetResourceHandle();

5

AfxSetResourceHandle(GetModuleHandle(_T("RegDll")));

6

CDialog dlg(4000);

7

dlg.DoModal();

8

AfxSetResourceHandle(temp);

9

}

其中TestOnly也是从RegDll中导出的函数,它什么都不做,只是返回一个1。我们使用它只是为了把RegDll加载进来。当然了,如果我们直接使用动态加载的方法,像下面这样直接LoadLibrary那更是没有问题了。

1

void CUseDllDlg::OnBnClickedOk()

2

{

3

HMODULE hm= LoadLibrary(_T("..//Debug//RegDll.dll"));

4

HINSTANCE temp = AfxGetResourceHandle();

5

AfxSetResourceHandle(GetModuleHandle(_T("RegDll")));

6

CDialog dlg(4000);

7

dlg.DoModal();

8

AfxSetResourceHandle(temp);

9

}

不过眼尖的读者可能会立即发现其实在上面这种情况下使用GetModuleHandle不是最好的选择。因为直接来个AfxSetResourceHandle(hm)就可解决问题了。

nginx 调用dll_使用DLL中的资源相关推荐

  1. C++ Builder创建和调用dll中的资源

    程序开发中经常会用到一些图标.图片.光标.声音等,我们称它们为资源(Resource).当多个窗口用到同样的资源时,可以将这些公共的资源放到一个dll文件里调用,这样,由于定位资源比在磁盘中定位文件花 ...

  2. 【Demo 0121】纯资源DLL中提取资源

    DLL 用途非常广泛,正如前几节中所有的,DLL可以封装函数.变量以及类. 而今天我们继续扩展DLL的用途,如何实现一个纯资源的DLL, 这个DLL没有入口也就是没有DllMain函数在VS中设置无入 ...

  3. 学习使用资源文件[11] - DLL 中的资源文件

    本例将把一张 bmp 图片, 以资源文件的方式嵌入 dll, 然后再调用. 第一步: 建一个 DLL 工程, 如图: 然后保存, 我这里使用的名称都是默认的. 第二步: 建一个资源原文件, 如图: 编 ...

  4. MFC中制作Dll中带对话框资源的动态库

    Data:2019/10/23 这篇文章本来是17年写的,现在对这边文章进行细化.更新的是有一些晚了些 想要在MFC中的dll里面添加对话框资源,首先必须的条件是,当前的dll库类型必须是可扩展的DL ...

  5. ASP.NET 2.0 中的资源与本地化

    转自MSDN 下载本文的代码:BasicInstincts2006_08.exe (878KB) 本页内容 控制页面级别的区域性设置 使用配置文件跟踪语言首选项 ASP.NET 2.0 中的资源文件 ...

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

    近来在论坛上很有多帖子问到如何使用DLL中的资源(包括对话框,图标等)的问题,现在笔者就来就此问题谈谈,包含在DLL内部使用资源,DLL中使用其它DLL中的资源和在应用程序中使用资源. 我们先以图标为 ...

  7. Win32 DLL和MFC DLL 中封装对话框

    Win32 DLL和MFC DLL 中封装对话框 分类: 挂挂2007-07-02 12:36 3344人阅读 评论(1) 收藏 举报 现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是 ...

  8. 如何查看exe或dll调用了什么dll

    [转载]如何查看exe或dll调用了什么dll呢 已有 19410 次阅读 2014-4-17 21:08|系统分类:科研笔记|文章来源:转载 Dependency Walker使用说明 在Windo ...

  9. Java通过JNI调用C++动态链接库dll,并打在jar包内 ——JNA-JNI(一)

    Java通过JNI调用C++动态链接库dll,并打在jar包内--JNA-JNI(一) 系列文章: Java通过JNI调用C++动态链接库dll,并打在jar包内 --JNA-JNI(一) Java使 ...

最新文章

  1. mongodb中简单的根据时间过滤进行查询
  2. vat可以退税吗_【涨知识】企业对外投资可以申请出口退税吗?
  3. git配置取消代理_「高手」如何优雅的解决 git 超时
  4. Spring boot中的Http压缩配置
  5. kvm初体验之八:调整vm的vcpu, memory, disk大小
  6. 流水灯c语言代码大全,单片机闪烁灯流水灯汇编代码大全
  7. 影楼——修图基本知识
  8. 正则表达式匹配非负数字
  9. 论文排版——Latex页眉页脚设定(中英都可以适用)
  10. 2018_2_3_Boolean Expressions_栈_模拟
  11. 【关于Log4j2】
  12. 数值模拟使用matlab实现案例
  13. MySQL学习笔记(1)——高可用组复制
  14. Java实现远程主机唤醒 (WOL)
  15. NEO4J-链路预测算法03-优先链接算法(Preferential Attachment)应用场景简介
  16. 使用Rational Performance Tester实现DB2 性能测试和监控
  17. arcgis直方图导出地图_利用Arcgis地图工具自动输出报告地图图纸
  18. 携职教育:初级会计考试明明不难,为什么通过率这么低?
  19. 从外部的js文件中获取ASPX页面的控件ClientID(get control reference from external javascript)...
  20. 学Linux网络管理有它就够了

热门文章

  1. 从链接上获取参数值, location.href上获取参数
  2. 主数据处理链碰到空数据节点不在继续执行的问题解决方案
  3. 关于移动端布局和pc端写法
  4. 详细了解文档对象模型(DOM)
  5. JS-内置对象内置构造函数事件-拖拽轮播图无缝滚动
  6. Iphone如何应对华为鸿蒙系统,鸿蒙2.0向iOS看齐 系统解决了 芯片怎么办?
  7. python yield: send, close, throw
  8. Matrix: android 中的Matrix (android.graphics.Matrix) (转)
  9. 使用svn进行本地代码管理
  10. CSS-Position