有程序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中的回调函数不需要引出,在主程序中使用时也比每次读回调函数地址方便得多

MFC的dll中控制资源问题的更多相关文章

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

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

  2. 实现MFC扩展DLL中导出类和对话框

    如果要编写模块化的软件,就要对对动态链接库(DLL)有一定的了解,本人这段时间在修改以前的软件时,决定把重复用的类和对话框做到DLL中,下面就从一个简单的例子讲起,如何实现MFC扩展DLL中导出类和对 ...

  3. MFC的DLL中实现定时器功能

    方法一:创建一个线程, 反复读系统时间不就可以了? 如果定时要求不严,用Sleep就可以了.DWORD WINAPI TimerThread(LPVOID pamaram) { UINT oldTic ...

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

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

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

    现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题.这里我们从Win32   DLL和MFC   DLL两个方面来分析并解决这个问题.     ...

  6. MFC的规则DLL中资源使用的问题

    今天刚刚做了一个静态链接到MFC的规则dll,即“Use MFC in a static library“,该dll用来显示一个窗体.然后在一个mfc可执行程序A.exe中调用这个dll文件,可以正常 ...

  7. 将MFC Grid control封装为DLL的做法及其在DLL中的使用方法

    MFCGrid control是一款非常优秀的网格控件,支持非常丰富的界面元素,如下图: 因而在数据库程序及报表程序应用较为广泛,其源码可以在下面下载到: MFC Grid control2.27源码 ...

  8. 在共享DLL中使用MFC

    使用VS2008,在项目属性中有一项MFC的使用,有三种设置: 1.使用标准Windows库 2.在共享DLL中使用MFC 3.在静态库中使用MFC          第一种顾名思义.        ...

  9. WIN32 DLL中使用MFC

    最近用WIN32 DLL,为了方便要用到MFC的一些库,又不想转工程,就网上找了很多方法,发现没有详细的介绍,有的也行不通,现在成功在WIN32 DLL中使用了MFC,记录一下以防以后用到忘记 一.修 ...

随机推荐

  1. jquery获取文档高度和窗口高度的例子

    jquery获取文档高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...

  2. 应注意的Flex&Bison潜规则

    1.Flex的二义性模式 语法分析器匹配输入时匹配尽可能多的字符串 如果两个模式都可以匹配的话,匹配在程序中更早出的模式. 针对这一点的理解,在语法分析文件当中,token的识别,应从特殊到一般的过程 ...

  3. 实现android支持多线程断点续传下载器功能

    多线程断点下载流程图: 多线程断点续传下载原理介绍: 在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度手机端下载数据时难免会出现无信号断线.电量不足等情况,所以需要断点续传功能根据下 ...

  4. SEO视频教程集合在线观看

    seo是搜索引擎优化(Search Engine Optimization)的英文缩写,是指为了从搜索引擎中获得更多的免费流量,从网站结构.内容建设方案.用户互动传播.页面等角度进行合理规划,使网站更 ...

  5. 【转】Android SDK Manager 更新方法

    在Android SDK Manager Setting 窗口设置HTTP Proxy server和HTTP Proxy Port这个2个参数,分别设置为: HTTP Proxy server:mi ...

  6. 关于linux下零散的东西 --慢慢补充

    一.截图     ,使用Shift+Ctrl+PrtSc就可以截图. 二.tar命令参数 c:表示压缩 x:表示解压 z:表示gzip的方式解/压缩 j:表示bzip2的方式解/压缩 三.串口终端ke ...

  7. Apache+PHP+MySql 的安装及配置

    每一项技术用的人多了,就会有人将其进行优化,做成一个简单.实用.大众化的工具,这对于初识者来说是非常方便的,但是对于长久学习或工作这方面的人技术人员来说是不可取的,所以还是要学习基础的实用方法.因此, ...

  8. 有关linux日志分析的详细介绍

    linux的日志文件可以帮助我们了解系统所处的状态,比如查出哪些用户有登入,及其它安全相关的一些问题. linux下的日志分析. 以下内容,部分参考了:探讨 linux 日志分析 这篇文章. 1.了解 ...

  9. 【Python笔记】异常处理

    1 什么是异常 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误. 当Pytho ...

  10. IIs上MP4、及SVG格式加载失败解决方式

    部署项目是遇到网页播放mp4文件时候,MP4文件不能加载的问题.那是因为IIS上MIME类型中没有添加MP4的格式,添加一下即可. 解决方案: 1.在IIS上选中你的网站,然后点击右边的MIME类型, ...