现在最常看见的关于DLL的问题就是如何在DLL中使用对话框,这是一个很普遍的关于如何在DLL中使用资源的问题。这里我们从Win32 DLL和MFC DLL两个方面来分析并解决这个问题。
1.Win32 DLL
在Win32 DLL中使用对话框很简单,你只需要在你的DLL中添加对话框资源,而且可以在对话框上面设置你所需要的控件。然后使用DialogBox或者CreateDialog这两个函数(或相同作用的其它函数)来创建对话框,并定义你自己的对话框回调函数处理对话框收到的消息。下面通过一个具体实例来学习如何在Win32 DLL中使用对话框,可以按照以下步骤来完成这个例子:
1)在VC菜单中File->New新建一个命名为UseDlg的Win32 Dynamic-Link Library工程,下一步选择A simple DLL project。
2)在VC菜单中Insert->Resource添加一个ID为IDD_DLG_SHOW的Dialog资源,将此Dialog上的Cancel按钮去掉,仅保留OK按钮。再添加一个ID为IDD_ABOUTBOX的对话框,其Caption为About。保存此资源,将资源文件命名为UseDlg.rc。并将resource.h和UseDlg.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.dll和UseDlg.lib。
接下来我们建立调用此DLL的应用程序,其步骤如下:
1)在VC菜单中File->New新建一个命名为Use的MFC 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.dll和UseDlg.lib两个文件复制到Use工程的Debug目录内。
5)编译生成Use.exe。
运行Use.exe,点击Button1按钮,可以看到一个名称为Dialog的非模态对话框弹出。点击上面的按钮,可以弹出模态对话框About。运行成功。
让我们来回顾一下在Win32 DLL中使用对话框的过程。
在DLL中,我们定义了两个对话框资源:IDD_DLG_SHOW和IDD_ABOUTBOX,并且导出了函数ShowDlg。在函数ShowDlg之中使用CreateDialog函数创建了非模态对话框IDD_DLG_SHOW,并指定了该对话框的回调函数DlgProc。在DlgProc之中处理了WM_INITDIALOG、WM_COMMAND和WM_CLOSE消息,以响应用户对对话框所做的动作。在处理按钮动作的时候,使用DialogBox函数创建IDD_ABOUTBOX这个模态对话框,指定其回调函数为AboutProc,并且在AboutProc中处理其相应消息。
在EXE中,我们使用隐式链接的方法来调用DLL,并使用DLL中导出的ShowDlg函数来调用DLL中的对话框。
在Win32 DLL中使用对话框就是这么简单,下面让我们来看一下在MFC DLL中如何使用对话框。
2.MFC DLL
在MFC DLL中使用对话框不像Win32 DLL中那么简单,主要是因为MFC程序中存在一个模块状态(Module State)的问题,也就是资源重复的问题。(此处的术语模块是指一个可执行程序,或指其操作不依赖于应用程序的其余部分但使用MFC运行库的共享副本的一个DLL(或一组DLL)。我们所创建的MFC DLL就是这种模块的一个典型实例。)
在每个模块(EXE或DLL)中,都存在一种全局的状态数据,MFC依靠这种全局的状态数据来区分不同的模块,以执行正确的操作。这种数据包括:Windows实例句柄(用于加载资源),指向应用程序当前的CWinApp和CWinThread对象的指针,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库的方法:静态链接到MFC的DLL和动态链接到MFC的DLL。下面我们就按照这两种类型的MFC DLL来介绍如何切换当前模块状态以正确的在MFC DLL中使用资源。
1、静态链接到MFC的DLL
静态链接到MFC的规则DLL与MFC库静态链接,则此时MFC库不能共享,所以MFC总是使用它所链接的DLL的模块状态。这样也就不存在管理模块状态的问题。但使用这种方法的缺点是DLL程序将会变大,而且会在程序中留下重复代码。下面给出的例子验证了这一点。本例可以按照以下步骤来完成:
1)在VC菜单中File->New新建一个命名为DLLStatic的MFC 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.dll和DLLStatic.lib。
继续使用上一节中的Use工程,将前面生成的DLLStatic.dll和DLLStatic.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时,不存在管理模块状态的问题。
Win32 DLL和MFC DLL 中封装对话框
时间: 2024-09-13 22:40:15
Win32 DLL和MFC DLL 中封装对话框的相关文章
VC++动态链接库(DLL)非MFC DLL介绍
4.1一个简单的DLL 第2节给出了以静态链接库方式提供add函数接口的方法,接下来我们来看看怎样用动态链接库实现一个同样功能的add函数. 如图6,在VC++中new一个Win32 Dynamic-Link Library工程dllTest(单击此处下载本工程附件).注意不要选择MFC AppWizard(dll),因为用MFC AppWizard(dll)建立的将是第5.6节要讲述的MFC 动态链接库. 图6 建立一个非MFC DLL 在建立的工程中添加lib.h及lib.cpp文件,源
静态.共享的规则MFC DLL/MFC扩展DLL详解
引言:在编写MFC程序的时候,通常需要编写dll库以供其他程序调用.关于MFC dll的相关知识很多很杂,这里特酷吧结合自己学习中遇到的问题专门整理了一些MFC dll的基础知识.本部分共上下两篇文章,本文为上篇,MFC DLL应用程序类型分为以下三种:(1)使用共享MFC DLL的规则DLL(2)带静态链接MFC的规则DLL(3)MFC扩展DLL下面重点解释一下这些DLL的含义区别:一,规则DLL首先谈谈所谓的"规则DLL":"规则DLL"是由"Regu
MFC DLL资源动态切换
在MFC使用过程中,遇到DLL资源与主EXE资源冲突问题. 出现这样的Bug,一时无从下手. 报错位置在核心代码中dlgcore.cpp. [cpp] view plaincopy BOOL AFXAPI _AfxCheckDialogTemplate(LPCTSTR lpszResource, BOOL bInvisibleChild) { ASSERT(lpszResource != NULL); HINSTANCE hInst = AfxFindResource
VC++.NET中定义和使用MFC DLL(一)
什么是DLL? DLL指的是动态链接库(Dynamic Link Library),它是一个可以被多个应用程序(甚至是不同语言编写的应用程序)同时调用的可执行二进制文件,是一个可共享的库.DLL是建立在客户/服务器通信的概念上,包含若干函数.类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL. 在下面我们将通过一个具体的例子来说明如何利用VC.Net定义一个DLL文件,并且在VC.Net的应用程序中调用,这个例子的主要
在Dll中创建对话框并调用
1.第一步创建一"MFC AppWizard (dll)"工程,接下来选择"Regular Dll using shared MFC DLL",点击"Finish". 2.添加一对话框资源到工程中,从菜单中选择Insert->Resource,添加一"Dialog" 选择"New",至此对话框已添加到DLL工程中. 3.为对话框添加一新类,如:CTest,基类为CDialog. 4.在MFCDLL.c
mfc-MFC、dll库中的对话框,无法用Tab键控件之间切换
问题描述 MFC.dll库中的对话框,无法用Tab键控件之间切换 在控件风格中已经加了tab相关的风格,控件属性Tabstop也改成了true,也Ctrl+D设置了控件响应tab键的顺序,可是按tab键就是不切换,同时上下键和回车键也没用,求大神解答
Delphi中在DLL动态链接库中封装VCL的MDI子窗体
不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下: 1var 2 DllApp: TApplication;//定义保存原DLL的TApplication对象 3 DllScr: TScreen;//定义保存原DLL的TScreen对象 4 5procedure UnProcDll(Reason: Integer); register; 6//重新定义DLL入口函数 7begin 8 if
Delphi中在DLL中封装的VCL窗体Tab键响应的问题
在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Tab按键并向活动子窗体发送一个Tab键按下的消息 2. 子窗体手动定义一个Tab键被按下的处理(需要用到FormKeyDown事件). 3. 移动到下一个焦点的WinAPI函数:Perform(WM_NEXTDLGCTL,0,0); 4.移动到上一个焦点的函数:Perform(WM_NEXTDLGCT
mfc dll工程中添加atl com接口使用类型库里自定义的数据类型
问题描述 mfc dll工程中添加atl com接口使用类型库里自定义的数据类型 vs2005环境下.详细见链接http://bbs.csdn.net/topics/391819620困扰好些天了.愁死了.新人菜鸟求各位大神帮看看. 解决方案 数据类型要转换的,好好看看对应的文档