在DLL中使用资源(一)

原创 2004年03月08日 11:29:00
DLL中使用资源(一)

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

1Win32 DLL

       Win32 DLL中使用对话框很简单,你只需要在你的DLL中添加对话框资源,而且可以在对话框上面设置你所需要的控件。然后使用DialogBox或者CreateDialog这两个函数(或相同作用的其它函数)来创建对话框,并定义你自己的对话框回调函数处理对话框收到的消息。下面通过一个具体实例来学习如何在Win32 DLL中使用对话框,可以按照以下步骤来完成这个例子:

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

1)在VC菜单中File->New新建一个命名为UseDlgWin32 Dynamic-Link Library工程,下一步选择A simple DLL project

 

2)在VC菜单中Insert->Resource添加一个IDIDD_DLG_SHOWDialog资源,将此Dialog上的Cancel按钮去掉,仅保留OK按钮。再添加一个IDIDD_ABOUTBOX的对话框,其CaptionAbout。保存此资源,将资源文件命名为UseDlg.rc。并将resource.hUseDlg.rc加入到工程里面。

 

3)在UseDlg.app中包含resource.h,并添加如下代码:

 

HINSTANCE hinst = NULL;

HWND hwndDLG = NULL;

 

BOOL CALLBACK DlgProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam);

BOOL CALLBACK AboutProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam);

extern "C" __declspec(dllexport) void ShowDlg();

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                    )

{

       switch(ul_reason_for_call)

       {

       case DLL_PROCESS_ATTACH:

              hinst = (HINSTANCE)hModule;

       case DLL_PROCESS_DETACH:

              break;

       }

    return TRUE;

}

 

extern "C" __declspec(dllexport) void ShowDlg()

{

       hwndDLG = CreateDialog(hinst,MAKEINTRESOURCE(IDD_DLG_SHOW),

NULL,(DLGPROC)DlgProc);

       ShowWindow(hwndDLG, SW_SHOW);

}

 

BOOL CALLBACK DlgProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam)

{

    switch(message)

    {

       case WM_INITDIALOG:

              return TRUE;

             

       case WM_COMMAND:

              if(LOWORD(wParam)==IDOK)

DialogBox(hinst,MAKEINTRESOURCE(IDD_ABOUTBOX),

hDlg,(DLGPROC)AboutProc);

              return TRUE;        

       case WM_CLOSE:

              DestroyWindow(hDlg);

              hwndDLG = NULL;

              return TRUE;

    }

    return FALSE;

}

 

BOOL CALLBACK AboutProc(HWND hDlg, UINT message,

WPARAM wParam, LPARAM lParam)

{

       switch(message)

    {

              case WM_CLOSE:

                     EndDialog(hDlg,NULL);

                     hwndDLG = NULL;

                     return TRUE;

    }

    return FALSE;

}

 

4)编译生成UseDlg.dllUseDlg.lib

 

接下来我们建立调用此DLL的应用程序,其步骤如下:

 

1)在VC菜单中File->New新建一个命名为UseMFC AppWizard(exe)工程,下一步选择Dialog Based之后点击Finish按钮。

 

2)在主对话框上面添加一个按钮,之后双击此按钮,会弹出Add Member Function的对话框,直接点击OK进入void CUseDlg::OnButton1()函数。并在此函数内添加一个函数调用:ShowDlg();

 

3)紧跟在#include语句后面加上如下代码:

 

extern "C" __declspec(dllexport) void ShowDlg();

#pragma comment(lib,"debug/UseDlg")

 

4)将上面UseDlg工程中生成的UseDlg.dllUseDlg.lib两个文件复制到Use工程的Debug目录内。

 

5)编译生成Use.exe

 

       运行Use.exe,点击Button1按钮,可以看到一个名称为Dialog的非模态对话框弹出。点击上面的按钮,可以弹出模态对话框About。运行成功。

 

       让我们来回顾一下在Win32 DLL中使用对话框的过程。

 

DLL中,我们定义了两个对话框资源:IDD_DLG_SHOWIDD_ABOUTBOX,并且导出了函数ShowDlg。在函数ShowDlg之中使用CreateDialog函数创建了非模态对话框IDD_DLG_SHOW,并指定了该对话框的回调函数DlgProc。在DlgProc之中处理了WM_INITDIALOGWM_COMMANDWM_CLOSE消息,以响应用户对对话框所做的动作。在处理按钮动作的时候,使用DialogBox函数创建IDD_ABOUTBOX这个模态对话框,指定其回调函数为AboutProc,并且在AboutProc中处理其相应消息。

 

EXE中,我们使用隐式链接的方法来调用DLL,并使用DLL中导出的ShowDlg函数来调用DLL中的对话框。

 

       Win32 DLL中使用对话框就是这么简单,下面让我们来看一下在MFC DLL中如何使用对话框。

2MFC DLL

       MFC DLL中使用对话框不像Win32 DLL中那么简单,主要是因为MFC程序中存在一个模块状态(Module State)的问题,也就是资源重复的问题。(此处的术语模块是指一个可执行程序,或指其操作不依赖于应用程序的其余部分但使用MFC运行库的共享副本的一个DLL(或一组DLL)。我们所创建的MFC DLL就是这种模块的一个典型实例。)

 

       在每个模块(EXEDLL)中,都存在一种全局的状态数据,MFC依靠这种全局的状态数据来区分不同的模块,以执行正确的操作。这种数据包括:Windows实例句柄(用于加载资源),指向应用程序当前的CWinAppCWinThread对象的指针,OLE模块引用计数,以及维护Windows对象句柄与相应的MFC对象实例之间连接的各种映射等。但当应用程序使用多个模块时,每个模块的状态数据不是应用程序范围的。相反,每个模块具有自已的MFC状态数据的私有副本。这种全局的状态数据就叫做MFC模块状态。

 

模块的状态数据包含在结构中,并且总是可以通过指向该结构的指针使用。当代码在执行时进入了某一个模块时,只有此模块的状态为“当前”或“有效”状态时,MFC才能正确的区分此模块并执行正确的操作。

 

例如,MFC应用程序可以使用下面代码从资源文件中加载字符串:

 

CString str;

str.LoadString(IDS_MYSTRING);

 

使用这种代码非常方便,但它掩盖了这样一个事实:即此程序中IDS_MYSTRING可能不是唯一的标识符。一个程序可以加载多个DLL,某些DLL可能也用IDS_MYSTRING标识符定义了一个资源。MFC怎样知道应该加载哪个资源呢?MFC使用当前模块状态查找资源句柄。如果当前模块不是我们要使用的正确模块,那么就会产生不正确的调用或者错误。

 

按照MFC库的链接方法,一个MFC DLL有两种使用MFC库的方法:静态链接到MFCDLL和动态链接到MFCDLL。下面我们就按照这两种类型的MFC DLL来介绍如何切换当前模块状态以正确的在MFC DLL中使用资源。

1、静态链接到MFCDLL

静态链接到MFC的规则DLLMFC库静态链接,则此时MFC库不能共享,所以MFC总是使用它所链接的DLL的模块状态。这样也就不存在管理模块状态的问题。但使用这种方法的缺点是DLL程序将会变大,而且会在程序中留下重复代码。下面给出的例子验证了这一点。本例可以按照以下步骤来完成:

 

1)在VC菜单中File->New新建一个命名为DLLStaticMFC AppWizard的工程,下一步选择Regular DLL with MFC statically linked

 

2)在工程中添加一个对话框资源,其ID为:IDD_ABOUTBOX。并在resource.h之中将IDD_ABOUTBOX 的数值改为100

 

3)在DLLStatic.cpp中定义如下函数:

 

void ShowDlg()

{

       CDialog dlg(IDD_ABOUTBOX);

       dlg.DoModal();

}

 

4)在DLLStatic.def文件中的EXPORTS语句中添加一行:ShowDlg,以导出ShowDlg函数。

 

5)编译生成DLLStatic.dllDLLStatic.lib

 

继续使用上一节中的Use工程,将前面生成的DLLStatic.dllDLLStatic.lib两个文件复制到工程的Debug目录内,并将

 

extern "C" __declspec(dllexport) void ShowDlg();

#pragma comment(lib,"debug/UseDlg")

 

这两行改为:

 

void ShowDlg();

#pragma comment(lib,"debug/DLLStatic")

 

编译并运行Use.exe。点击按钮,可以看到DLLStatic中的模态对话框弹出。

 

本例中,可以注意到DLL中所定义的About对话框资源与EXE中所定义的About对话框资源ID完全相同,但是当我们点击Use.exe上面的按钮时,弹出的是DLL中的模态对话框。说明,当使用静态链接到MFC的规则DLL时,不存在管理模块状态的问题。

 

连载:在DLL中使用资源(二)


----------rivershan 原创于2004.3.8,转载请注明出处

使用MFC DLL中的资源

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

DLL+资源模块切换

MFC程序中存在一个模块状态(Module State)的问题,也就是资源重复的问题。(此处的术语模块是指一个可执行程序,或指其操作不依赖于应用程序的其余部分但使用MFC运行库的共享副本的一个DLL(...
  • Alexander_Frank
  • Alexander_Frank
  • 2016年08月09日 15:15
  • 553

C#嵌入dll到资源释放的问题

http://blog.csdn.net/kikaylee/article/details/44536231  有些程序运行的时候,可能调用外部的dll,用户使用时可能会不小心丢失这...
  • mosangbike
  • mosangbike
  • 2017年01月18日 09:29
  • 1197

[WPF] 嵌入资源到DLL,并解决PNG图片问题

在WPF有很多种资源文件存储的方式,就图片的存储就麻烦到极点。 最近自己弄一个项目就遇到这样那样的问题,现在把自己的使用方法总结出来给大伙借鉴借鉴! 在我的项目中,我并不想把所有的图片都存放在文件夹下...
  • qiujuer
  • qiujuer
  • 2014年01月06日 16:46
  • 4318

VC中使用纯资源dll实现多语言版本

用VC纯资源dll解决国际化问题这的确是个老话重谈了,因为这里面确实也没有什么可以称的上技术含量的,只是实现起来有点烦琐,不过我还是要写出来,希望刚接触这方面的同行们不至于走太多的弯路。  由于...
  • wander_wang
  • wander_wang
  • 2015年06月17日 20:43
  • 886

MFC 中切换资源的两种方式

方法一: AFX_MANAGE_STATE(AfxGetAppModuleState());// MFC扩展dll或AFX_MANAGE_STATE( AfxGetStaticModuleStat...
  • Alexander_Frank
  • Alexander_Frank
  • 2016年08月10日 13:44
  • 862

从内存资源中加载DLL:CMemLoadDll源码整理

头文件 /*****MemLoadDll.h*****/ #if !defined(Q_OS_LINUX) #pragma once typedef BOOL (__stdcall *Pro...
  • tianshi_1988
  • tianshi_1988
  • 2016年04月22日 18:00
  • 980

DLL和EXE加载包在自身内部的资源文件

1、插入资源的方法       insert-->resource-->import,在出现的对话框中选择一个要作为资源的文件,接着在出现的对话框中Resource type:下面的框中随便自己输入...
  • mengyafei43
  • mengyafei43
  • 2013年08月26日 14:33
  • 3448

C#嵌入dll到资源释放的问题

有些程序的时候,可能调用外部的dll,这个时候提供给客户的时候,可能经常不小心丢失这些dll,因此可以考虑将这些dll嵌入到资源中,启动的时候进行释放。对于托管的dll,可以用打包软件合成一个exe(...
  • kikaylee
  • kikaylee
  • 2015年03月22日 11:50
  • 7996

VC程序运行时导出资源、DLL、EXE

在VC可以在可执行程序和调用动态静态库时动态的导出资源、DLL、exe。 首先把想要导出的资源导入,这里简单描述DLL资源导入的步骤: 1.在Resource View(资源视图)中查找到相应工程...
  • cardinal_508
  • cardinal_508
  • 2013年03月02日 13:11
  • 3774
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在DLL中使用资源(一)
举报原因:
原因补充:

(最多只允许输入30个字)