MFC的dll中控制资源问题-阿里云开发者社区

开发者社区> double2li> 正文

MFC的dll中控制资源问题

简介: 有程序EXE和DLL,其中DLL中有1个函数用来显示对话框,被EXE调用。当EXE和DLL都为Release或Debug时,没有任何问题,但EXE为Release、DLL为Debug时,就会出错。该DLL是用VC提供的MFC Extension DLL,函数的代码如下:HINSTANCE hInst...
+关注继续查看

有程序EXE和DLL,其中DLL中有1个函数用来显示对话框,被EXE调用。
当EXE和DLL都为Release或Debug时,没有任何问题,但EXE为Release、
DLL为Debug时,就会出错。该DLL是用VC提供的MFC Extension DLL,
函数的代码如下:
HINSTANCE hInstOld = AfxGetResourceHandle(); // 该句出错
HINSTANCE hInstNew = GetModuleHandle("T01Test.dll");
AfxSetResourceHandle(hInstNew);

CHahaDlg dlg;
dlg.DoModal();

AfxSetResourceHandle(hInstOld);

 

 

长久以来,把界面的信息单独存为一个DLL一直是很多商业软件的作法,比如VC、InstallShield等等,这样做的好处是,如果要做多语言版本,只要写出不同的DLL来,在主程序中使用时调用不同的DLL就行,当然现在还有一种流行的方法是使用INI,读存也非常方便。最近在网上转了转,发现竟没有一篇关于如何读取DLL中资源的文章,虽然Iczelion的Win32ASM教程中第26课"Splash Screen"讲到了读取DLL中的图片,但不知是这种问题太简单了还是其它什么原因,Iczelion没有讲解这段代码的意思,于是乎决定写一篇关于DLL资源读取的文章,望大家不要$%@%@^%@%。
我们看一下这些函数:
HBITMAP LoadBitmap(HINSTANCE hInstance,LPCTSTR lpBitmapName)
HICON LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName)
HMENU LoadMenu(HINSTANCE hInstance,LPCTSTR lpMenuName)
int LoadString(HINSTANCE hInstance,UINT uID,LPTSTR lpBuffer,int BufferMax)

int DialogBoxParam(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpTemplateName, // identifies dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // pointer to dialog box procedure 
LPARAM dwInitParam // initialization value
);

HWND CreateDialogParam(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpTemplateName, // identifies dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // pointer to dialog box procedure 
LPARAM dwInitParam // initialization value
);
这些都是常用的读取资源的函数,它们都有一个共同点:第一个参数需要的是要读取的包含资源的程序的模块句柄,那么,关键就在这个句柄,因为我们在读取本身程序资源的时候,肯定是提供用GetModuleHandle函数获得的句柄,这个句柄就是当前程序的实例句柄,如果要读取DLL中的资源,很显然的,我们需要提供DLL的句柄,那么这个DLL句柄怎么得到呢?很简单,我们在使用LoadLibrary函数时,返回的值就是读取的DLL的句柄,于是,我们读取DLL中的资源,只需要这样:
invoke LoadLibrary,DLL_FILENAME
mov DLL_HANDLE,eax
invoke LoadBitmap,DLL_HANDLE,BITMAP_ID
invoke LoadIcon,DLL_HANDLE,ICON_ID
invoke LoadMenu,DLL_HANDLE,MENU_ID
invoke LoadString,DLL_HANDLE,STRING_ID,StrBuffer,sizeof StrBuffer
invoke DialogBoxParam,DLL_HANDLE,DLG_NAME,hParent,DlgProc,lParam
其它的函数就不多说,着重讲一下DialogBoxParam与CreateDialogParam,因为其它函数不需要回调函数,读取之后句柄可以一直到程序结束才释放。我们讨论的就是DialogBoxParam与CreateDialogParam回调函数的方法。
我曾上过当,把DialogBoxParam与CreateDialogParam的回调函数写在主程序中,相信有很多的朋友也是写在主程序中,然后直接把回调过程地址传给DialogBoxParam与CreateDialogParam,其实,这是一种错误的方法,正确的方法是,我们必须把回调函数写在对话框资源本身的DLL中,在主程序用DialogBoxParam与CreateDialogParam显示对话框时提供DLL中的回调函数地址,当然,对纯提供资源的DLL,它们不同的只是界面语言文字,这个把回调函数写在主程序中更加好,如果是插件呢?如果主程序使用了很多的DLL呢?对于插件而言,回调函数是必须在DLL中的,主程序使用很多DLL时,把回调函数都写在主程序中,就算能正常运行,但是DLL有变动,就算是一个小修改,也不得不重新更改主程序,所以,我的建议是:除了纯资源DLL,编写DLL时,对话框的回调函数一定要写在DLL本身中。
可是,如果在主程序中就这样子使用DLL对话框,那么,DLL对话框的回调函数就必须引出,这样主程序才能获得回调函数地址,就像这样:
invoke GetProcAddress,DLL_HANDLE,DlgProcName
invoke DialogBoxParam,DLL_HANDLE,DLG_NAME,hWnd,eax,NULL
;DlgProcName就是DLL中引出的回调函数
这段代码看起来非常简洁,也完全能正常工作,可是想一想,如果在程序其它的地方要不停的使用DLL中的对话框,不仅上述工作很烦人,更烦的是,我们必须把所有的回调函数全部引出,其实我们完全可以这样做:
在DLL中编写一个函数LoadDialog,如下:
LoadDialog proc hInstance,hWnd,ID
.if ID==100
mov eax,offset DlgProc0
.elseif ID==101
mov eax,offset DlgProc1
.elseif ID==102
mov eax,offset DlgProc2
.elseif ID==103
mov eax,offset DlgProc3
.end if
invoke DialogBoxParam,hInstance,ID,hWnd,eax,NULL
ret
LoadDialog endp
;DlgProc0、DlgProc1、DlgProc2、DlgProc3都是DLL中的回调函数
那么,我们在主程序中调用时就只需这样:
invoke GetProcAddress,DLL_HANDLE,DlgProcName ;DlgProcName="LoadDialog"
mov LoadDialog,eax
push ID
push hWnd
push DLL_HANDLE
call [LoadDialog]
只需在程序开头获取到LoadDialog的地址后,在任何地方调用不同的对话框只需要提供不同的ID即可,就像这样:
push 101
push hWnd
push DLL_HANDLE
call [LoadDialog]
这样做,不仅DLL中的回调函数不需要引出,在主程序中使用时也比每次读回调函数地址方便得多

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
MSVCP110D.DLL丢失问题
    将Debug.win32文件夹拷贝至其它机子运行(机子上无VS),点击运行时出现MSVCP110D.DLL缺失提示。           1、在项目中,C/C++ -- Code Generation -- Runtime Library:此时大部分的为Multi-threaded Debug DLL (/MDd)。在目标机子运行时,需要提供相应的MSVCR.DLL库。我们将项
920 0
ECS控制台支持资源组
为了提升企业管理云资源的效率,阿里云提出了资源组的概念,将云资源加入到资源组中,不仅易于管理和维护云资源,也企业管理层面提供了不同的管理视角,关于资源组的更多信息请到企业控制台了解详情 [企业控制台](https://enterprise.console.aliyun.com/)
1879 0
chrome 等浏览器不支持本地ajax请求的问题
chrome 等浏览器不支持本地ajax请求的问题   XMLHttpRequest cannot load file:///D:/WWW/angularlx/ui-router-test/template/content.
1222 0
深入理解 Promise 五部曲:2. 控制权转换问题
[转, 原文地址:http://segmentfault.com/a/1190000000591382 ] 在上一篇深入理解Promise五部曲:1.异步问题中,我们揭示了JS的异步事件轮询并发模型并且解释了多任务是如何相互穿插使得它们看起来像是同时运行的。
962 0
duilib入门之贴图描述、类html文本描述、动态换肤、Dll插件、资源打包
转载自duilib入门文档 贴图描述:          Duilib的表现力丰富很大程度上得益于贴图描述的简单强大。Duilib的贴图描述分为简单模式和复杂模式两种。
1495 0
如何解决MFCO42D.dll 0xC0000005:Access Violation问题
如何解决MFCO42D.dll 0xC0000005:Access Violation问题 一.问题的提出: 在甲电脑,就是笔者的电脑,程序可以正常运行; 但是在乙电脑,就是同事的电脑,程序运行却出现(MFCO42D.DLL):0xC0000005:Access Violation错误信息。
836 0
30个非常精美的免费用户界面 PSD 素材资源下载
  免费 PSD 素材资源对于网页设计师来说都非常有用,网上也有很多提供高品质的 PSD 素材免费下载的网站。目前最流行的免费 PSD 素材是用户界面(UI)元素,这些元素对于设计网站和应用程序非常有用。
794 0
VB动态加载纯DLL资源
一、纯DLL资源的制作            打开VC6.0 创建一个基于win32的动态链接库   下一步中,要选择A sinmple Dll project              然后加载资源(注意对于超过256色的位图,VC不能编辑,不过这没关系)           可以加载位图、图标、字符串等,这是加载后的情况      资源添加完毕后,编译。
405 0
常见的浏览器兼容性问题总结
1. 不同浏览器的标签默认外补丁margin和内补丁padding不同 发生概率:100% 解决方案:使用CSS通配符*,设置内外补丁为0 *{ margin: 0; padding: 0;} 2.
1513 0
PyQt的图片资源的路径问题。
百度到的PyQt的添加资源大部分都是通过Qt Creater添加资源的,适用于拖拽形成的界面。   问题一:纯粹手写的界面,添加资源呢?   文件夹路径: |----img     |--aa.jpg |----view     |---View.py Main.py 问题二:   在如上显示的文件夹下,View.py的界面在View.py中调用能正常显示,如果在Main.py中调用View.py,图片资源就不能正常显示了。
943 0
+关注
double2li
一个在IT行业摸爬滚打的老司机
2870
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载