友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
VC语言6.0程序设计从入门到精通-第55部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
即可生成动态链接库。
图 10…4 生成 Regular Dll using shared MFC DLL
·264 ·
…………………………………………………………Page 276……………………………………………………………
第 10 章 动态链接库
添加一个对话框资源到工程中,从菜单中依次选择“Insert ”→“Resource ”项,添加“Dialog ”
选择“New ”项,至此对话框已添加到 DLL 工程中。
为对话框添加 CTest 类,基类为 CDialog 。同时在 MFCDLL。cpp 中( 因创建的工程为
MFCDLL)添加测试接口函数如下:
extern 〃C〃 __declspec(dllexport) void Show()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CTest test;
test。DoModal ();
}
静态连接到 MFC 的动态链接库只被 Visual C++ 的专业版和企业版所支持。该类 DLL 应
用程序里头的输出函数可以被任意的 Win32 程序使用,包括使用 MFC 的应用程序。输入函
数有如下形式:
extern 〃C〃 EXPORT YourExportedFunction();
如果没有 extern 〃C〃修饰,输出函数仅仅能从 C++代码中调用。
DLL 应用程序从 CWinApp 派生,但没有消息循环。
动态链接到 MFC 的规则 DLL 应用程序里头的输出函数可以被任意 Win32 程序使用,包
括使用 MFC 的应用程序。但是,所有从 DLL 输出的函数应该以如下语句开始:
AFX_MANAGE_STATE(AfxGetStaticModuleState())
此语句用来正确地切换 MFC 模块状态。
因为一般在动态链接库中使用嵌入资源是通过动态链接的,所以测试接口函数作了上述
程序片断的声明和定义。
在要输出的函数、类、数据的声明前加上_declspec(dllexport) 的修饰符,表示输出。
_declspec(dllexport)在 C 调用约定、C 编译情况下可以去掉输出函数名的下划线前缀。extern
〃C〃使得在 C++ 中使用 C 编译方式成为可能。在“C++ ”下定义〃C〃函数,需要加 extern 〃C〃
关键词。用 extern 〃C〃来指明该函数使用 C 编译方式。输出的〃C〃函数可以从〃C〃代码里调用。
下面以具体示例作详细介绍。在一个 C++文件中,有如下函数:
extern 〃C〃 {void __declspec(dllexport) __cdecl Test(int var);}
其输出函数名为 Test 。
MFC 提供了一些宏,就有这样的作用。代码如下:
AFX_CLASS_IMPORT :__declspec(dllexport)
AFX_API_IMPORT :__declspec(dllexport)
AFX_DATA_IMPORT :__declspec(dllexport)
AFX_CLASS_EXPORT :__declspec(dllexport)
AFX_API_EXPORT :__declspec(dllexport)
AFX_DATA_EXPORT :__declspec(dllexport)
AFX_EXT_CLASS : #ifdef _AFXEXT
AFX_CLASS_EXPORT
#else
·265 ·
…………………………………………………………Page 277……………………………………………………………
Visual C++ 6。0 程序设计从入门到精通
AFX_CLASS_IMPORT
AFX_EXT_API :#ifdef _AFXEXT
AFX_API_EXPORT
#else
AFX_API_IMPORT
AFX_EXT_DATA :#ifdef _AFXEXT
AFX_DATA_EXPORT
#else
AFX_DATA_IMPORT
像 AFX_EXT_CLASS 这样的宏,如果用于 DLL 应用程序的实现,则表示输出(因为
_AFX_EXT 被定义,通常是在编译器的标识参数中指定该选项/D_AFX_EXT )。如果用于使
用 DLL 的应用程序中,则表示输入(_AFX_EXT 没有定义)。
要输出整个的类,对类使用_declspec(_dllexpot) ;要输出类的成员函数,则对该函数使用
_declspec(_dllexport) 。代码如下:
class AFX_EXT_CLASS CTextDoc : public CDocument
{
…
}
extern 〃C〃 AFX_EXT_API void WINAPI InitMYDLL();
为了调用动态链接库的资源,新建了一个基于对话框的 MFC 应用程序测试函数接口,
测试的主要代码如下:
void CTestDlg::OnOK()
{
// TODO: Add extra validation here
typedef void (WINAPI * TESTDLL)(); //定义函数指针类型 TESTDLL
HINSTANCE hmod; //动态链接库实例句柄
hmod = ::LoadLibrary (〃mfcdll。dll〃); //加载 mfcdll。dll 动态链接库
if(hmod==NULL)
{
AfxMessageBox(〃Fail〃); //如果加载动态链接库失败
}
TESTDLL lpproc; //定义接收导出函数的函数指针 lpproc
lpproc = (TESTDLL)GetProcAddress (hmod;〃Show〃); //得到导出函数 Show 的地址
if(lpproc!=(TESTDLL)NULL) // 当成功得到导出函数地址的时候
(*lpproc)(); //执行动态链接库中的导出函数
FreeLibrary(hmod); //释放动态链接库资源
·266 ·
…………………………………………………………Page 278……………………………………………………………
第 10 章 动态链接库
// CDialog::OnOK();
}
执行的结果如图 10…5 所示。从图中可以看出,可执行程序成功地调用了动态链接库中的
对话框资源。
图 10…5 调用 DLL 中的对话框资源
10。6 界面汉化示例
在 Windows 系统中,应用程序开发者可以通过利用动态链接库,用一套源代码来支持多
种文字。本节将通过一个界面汉化的示例来演示动态链接库中资源的应用方法。
利用 Visual C++编程,可以把所有的可见资源封装在一个资源动态链接库中,以简化本
地化工作。一般情况下,资源包含在应用程序中,但也可以通过调用 AfxSetResourceHandle
函数指向一个不同的单元以完成资源的引用。本例就是首先调用该函数从动态链接库中采集
到所有的应用程序可用资源,然后通过调用 GetSystemDefaultLangID 函数判断系统默认语种,
以载入不同语种的资源动态链接库实现界面与系统的自动适应。
实例 10…2:界面汉化实例。源代码在光盘中“10实例 10…2”目录下。
本节以创建一个默认语种为简体中文的 Languages 应用程序为例,进一步详细说明。该
程序不含任何资源,应用程序根据系统的语种设置连接对应的资源链接库,以完成对中文和
英文两种语言的支持。
附带光盘中的 chinese。dll 和 english。dll 两个动态链接库分别封装了中文资源和英文资源,
下面具体介绍 Languages 应用程序的实现过程。
1.创建 Languages
用 MFC AppWizad(exe)创建新项目的工作区,选择 Simple Document 类型、中国中文(其
他的选项选择默认) ,并且为了明确,将工作区目录改为“多语种支持”。
2 .添加数据成员
由于要动态地装入资源链接库,所以需要保存链接库的句柄以便在程序结束的时候释放
·267 ·
…………………………………………………………Page 279……………………………………………………………
Visual C++ 6。0 程序设计从入门到精通
资源。将下述数据成员添加到 CLanguagesApp 类中,代码如下:
protected:
//资源链接库句柄
HINSTANCE m_hLangDLL;
3 .修改 InitInstance() 函数
应用程序需要判别系统的默认语种,并装入对应的资源链接库。将下面的代码加到
InitInstance 函数中,代码如下:
BOOL CLanguagesApp::InitInstance()
{
AfxEnableControlContainer();
// 判定系统默认语种
WORD wLangPID=PRIMARYLANGID(::GetSystemDefaultLangID());
// 载入资源动态链接库
switch( wLangPID)
{
case LANG_CHINESE:
m_hLangDLL=::LoadLibrary(〃chinese。dll〃);
break ;
default:
m_hLangDLL=::LoadLibrary(〃english。dll〃);
break;
}
if(!m_hLangDLL)
{
AfxMessageBox(_T(〃无法装载资源链接库!〃)) ;
return FALSE ;
}
// 连接资源
AfxSetResourceHandle(m_hLangDLL) ;
……
}
其中,操作系统所使用的默认语种由 Win 32 函数 GetSystemDefaultLangID 取得。宏
PRIMARYLANGID 取出主语言标识符进行判断,以正确选择应该调用的链接库。链接库的
加载由 Win32 函数 LoadLibrary 实现。程序中所使用的资源库由 AfxSetResourceHandle 函数
指定。
4 .处理 ExitInstance() 函数
程序退出时使用 Win 32 函数 FreeLibrary 卸载已经装入的动态链接库。将下列代码添加
到 ExitInstance 函数中,代码如下:
·268 ·
…………………………………………………………Page 280……………………………………………………………
第 10 章 动态链接库
int CLanguagesApp::ExitInstance()
{
//释放资源链接库
if(m_hLangDLL)
AfxFreeLibrary(m_hLangDLL);
return CWinApp::ExitInstance();
}
5 .修改 OnDraw
为了说明是从资源链接库中动态地获取数据而不是从程序的执行体中获取,该程序从资
源链接库中获取了一个字符串,并绘制在屏幕上。代码如下:
void CLanguagesView::OnDraw(CDC* pDC)
{
CLanguagesDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CString strMsg;
strMsg。LoadString(IDS_HELLO);
pDC…》TextOut(60;15;strMsg);
// TODO: add draw code for native data here
}
6 .从项目中移走 Languages。rc 文件
因 为 Languages 自 身 并不 需 要 含 有 任 何 资 源 , 所 以 可 以从 项 目 列 表 文 件 中 移 走
Languages。rc 文件(并不删除)。ClassWizad 不允许项目不包含资源文件,可以创建一个空资
源文件并将其加入到项目中,然后重建信息文件(Languages。CLW ),使得 ClassWizad 可以继
续管理程序的消息处理 。但在本例中所有的函数都已经加入,可不必为项目创建空资源文件。
7 .建立项目
修 改 设 置 , 选 择 “ Project| Setting … ” 菜 单 命 令 , 在 Link 标 签 下 将 输 出 文 件 名
DebugLanguages。exe 改为 Languages。exe 。编译项目,如果应用程序中没有任何资源,会出
现找不到资源链接库的错误,下面的一系列步骤为本项目分别创建简体中文和美国英语的资
源链接库。在这两个链接库建立后,把它们放到 Languages 项目目录中,程序就可以运行了。
建立中文资源链接库的主要步骤如下。
o 选择 Regular DLL…based 应用程序并单击“Finish ”按钮完成创建。动态链接库项目只
包含资源,不需要其他文件,所以从项目中删除所有其他文件。
o 把 Languages 相关的资源文件拷贝到 Language_chinese 项目的对应目录下。
o 把 Languages。rc 加入到 Language_chinese 项目中,使得 Languages。rc 为项目中的惟一
文件。
o 在串资源表(String Table)中添加串 IDS_HELLO=200
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!