AFX_MANAGE_STATE(AfxGetStaticModuleState())
 

先看一个例子:

1、创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源。指定该对话框ID如下:
              #define IDD_DLL_DIALOG 2000

2、创建一个基于对话框的mfc应用程序,它包含两个对话框资源,IDD_UI_DIALOG和IDD_EXE_DIALOG。并将后者的ID指定如下:
              #define IDD_EXE_DIALOG 2000
其中前者是这个应用程序的用户界面,单击上面的按钮,将弹出一个对话框。部分代码如下:
// in DLL
void CDLL::ShowDlg(void)
{
       CDialog dlg(IDD_DLL_DIALOG); //打开ID为2000的对话框
       dlg.DoModal();
}
// in EXE
void CEXE::OnButtonClick()
{
       ShowDlg();
}

3、单击按钮,弹出的不是期望的DLL中的对话框IDD_DLL_DIALOG,而是应用程序中的对话框IDD_EXE_DIALOG。

解释:

1、应用程序进程本身及其调用的每个DLL模块都具有一个全局唯一的HINSTANCE句柄,它们代表了EXE或DLL模块在进程虚拟空间中的起始地址。(进程本身的模块句柄一般为0x400000,而DLL模块的缺省句柄为0x10000000。如果程序同时加载了多个DLL,则每个DLL模块都会有不同的HINSTANCE。应用程序在加载DLL时对其进行了重定位)。
2、共享MFC DLL(或MFC扩展DLL)的规则DLL涉及到HINSTANCE句柄问题,HINSTANCE句柄对于加载资源特别重要。EXE和DLL都有其自己的资源,而且这些资源的ID可能重复,如果应用程序与规则DLL共享MFC DLL(或MFC扩展DLL),那么将总是默认使用EXE的资源。
3、因此应用程序需要通过资源模块的切换来找到正确的资源。如果应用程序需要来自于DLL的资源,就应将资源模块句柄指定为DLL的模块句柄;如果需要EXE文件中包含的资源,就应将资源模块句柄指定为EXE的模块句柄。

解决办法:

1、在DLL中改进:

方法1。

// in DLL
void CDLL::ShowDlg(void)
{
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
       CDialog dlg(IDD_DLL_DIALOG); //打开ID为2000的对话框
       dlg.DoModal();
}

注:AFX_MANAGE_STATE(AfxGetStaticModuleState());一定是作为接口函数的第一条语句。
       其功能是在栈上(这意味着其作用域是局部的)创建一个AFX_MODULE_STATE类的实例,并将其指   针pModuleState返回。
       AFX_MODULE_STATE类利用其构造函数和析构函数进行存储模块状态现场及恢复现场的工作。
       该宏用于将pModuleState设置为当前的有效模块状态。当离开该宏的作用域时(也就离开了pModuleState所指栈上对象的作用域),先前的模块状态将由类AFX_MODULE_STATE的析构函数恢复。(即自动恢复)

方法2。

// in DLL
void CDLL::ShowDlg(void)
{
       HINSTANCE save_hInstance = AfxGetResourceHandle();
       AfxSetResourceHandle(theApp.m_hInstance);
       CDialog dlg(IDD_DLL_DIALOG); //打开ID为2000的对话框
       dlg.DoModal();
       AfxSetResourceHandle(save_hInstance);    
}

注:AfxGetResourceHandle:获取当前资源模块句柄;AfxSetResourceHandle:设置程序目前要使用的资源模块句柄。
       同方法1比较,方法2能够灵活地设置程序的资源模块句柄,而方法1则只能在DLL接口函数退出的时候才会恢复模块句柄。

2、在应用程序中改进:

// in EXE
void CEXE::OnButtonClick()
{
       HINSTANCE exe_hInstance = GetModuleHandle(NULL);
      HINSTANCE dll_hInstance = GetModuleHandle("SharedDll.dll");
      AfxSetResourceHandle(dll_hInstance); //切换状态
       ShowDlg();
      AfxSetResourceHandle(exe_hInstance); //恢复状态
}

注:使用状态切换的情况:当DLL导出函数包含MFC资源、类或者需要创建窗口时。

MFC资源冲突解决方法的更多相关文章

  1. IIS上虚拟站点的web.config与主站点的web.config冲突解决方法 分类: ASP.NET 2015-06-15 14:07 60人阅读 评论(0) 收藏

    IIS上在主站点下搭建虚拟目录后,子站点中的<system.web>节点与主站点的<system.web>冲突解决方法: 在主站点的<system.web>上一级添 ...

  2. IIS上虚拟目录下站点的web.config与根站点的web.config冲突解决方法

    IIS7.5上在站点下部署虚拟目录,访问虚拟目录下的项目提示与父节点配置冲突.,节点与的<system.web>节点与主站点的<system.web>冲突解决方法: 在站点下的 ...

  3. 转:git合并冲突解决方法

    git合并冲突解决方法 1.git merge冲突了,根据提示找到冲突的文件,解决冲突 如果文件有冲突,那么会有类似的标记 2.修改完之后,执行git add 冲突文件名 3.git commit注意 ...

  4. apache与IIS共用80端口冲突解决方法

    如果同一台电脑安装了apache和iis,会提示80端口冲突,如何解决apache与iis 80端口冲突的问题呢,并且同时使用apache和iis 将apache设为使用80端口,IIS使用其它端口, ...

  5. 汇总Anaconda与ROS冲突解决方法

    汇总一下在网上找到的Anaconda与ROS冲突解决方法,如果还有其他人找到其他方法,欢迎留言. anaconda和ros的安装就不介绍了. 1. 在某视频网站上一个印度小哥提出的方法 安装完成后,在 ...

  6. tornado和vue的模板冲突解决方法

    tornado和vue的模板冲突解决方法 Vue的插值表达式和tornado的模板都为一对花括号,可以通过修改vue的插值表达式的符号来解决这个问题,具体方法如下: var vm = new Vue( ...

  7. MFC常见问题以及解决方法(1)_MFC下文本编辑框按下回车后窗口退出

    这里主要介绍遇到这种方法的解决方案,解决方法可能有多种,但这里只给出有效的一种,这里不会详细说明出现问题的原因以及为什么这样解决,想了解更多可以百度,写这个主要是防止以后忘记,做个简单的笔记. 问题: ...

  8. 常见JS(JavaScript)冲突解决方法

    1.一般JS冲突解决办法 a.最容易出现的就是js的命名冲突 ①.变量名冲突 变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScr ...

  9. Hash算法冲突解决方法分析

    采用开放定址法处理散列表的冲突时,其平均查找长度?  高于链接法处理冲突 低于二分查找 开放定址法:一旦发生冲突,就去寻找下一个空的散列地址,只要散列地址够大,空的地址总会找到 链地址法: 一旦发生冲 ...

随机推荐

  1. hibernate中 inverse的用法(转载)

    http://blog.csdn.net/xiaoxian8023/article/details/15380529 一.Inverse是hibernate双向关系中的基本概念.inverse的真正作 ...

  2. [python爬虫] Selenium定向爬取虎扑篮球海量精美图片

    前言: 作为一名从小就看篮球的球迷,会经常逛虎扑篮球及湿乎乎等论坛,在论坛里面会存在很多精美图片,包括NBA球队.CBA明星.花边新闻.球鞋美女等等,如果一张张右键另存为的话真是手都点疼了.作为程序员 ...

  3. paip.截取字符串byLastDot方法总结uapi python java php c# 总结

    paip.截取字符串byLastDot方法总结uapi python java php c# 总结 ========uapi   left_byLastDot   right_byLastDot 目前 ...

  4. paip.java 调用c++ dll so总结

    paip.java 调用c++ dll so总结 ///////JNA (这个ms sun 的) 我目前正做着一个相关的项目,说白了JNA就是JNI的替代品,以前用JNI需要编译一层中间库,现在JNA ...

  5. mysql高级排序&高级匹配查询示例

    在大多数应用场景下,我们使用mysql进行查询时只会用到'=', '>' , '<' , in, like 等常用的方法,看起来,大多数情况下,已经足以应付我们的小型应用了.不过,在一些特 ...

  6. 使用Jsoup 爬取网易首页所有的图片

    package com.enation.newtest; import java.io.File; import java.io.FileNotFoundException; import java. ...

  7. Tomcat启动后快逸报表报错的解决方法

    SSH2+EasyUI项目用到了快逸报表,启动Tomcat后系统报错: Report System initing...... [2015-06-04 15:03:05] runqianReportL ...

  8. c#之第三课

    学习获取终端输入的参数并且打印,以及使用循环. using System; public class CommandLine { public static void Main(string[] ar ...

  9. 我用了13行代碼開發出来的PHP框架

    我只用13行代碼開發的PHP框架,如果您對框架不理解,不知道框架究竟幫您做了什麽事,可以下載此框架看一下, 另外如果您想開發自己的框架也可以由這個框架的思路進行擴展. 源碼下載地址:http://do ...

  10. C# 设置和获取一个字节的某一位的值的方法

    自己工作中遇到需要对单字节的高位.低位进行赋值,即一个字节byte,想要给每一位都赋值,这个值是动态来的,是0或是1. 好不容易收集到一些珍贵资料,整理一下: 一.设置 方法code: /// < ...