b) 为“确定”按钮添加单击事件代码:
void CSysTimeApplicationDlg::OnBnClickedOk( ) { // TODO: 在此添加控件通知处理程序代码 SYSTEMTIME st; GetTime(&st); CString StrMessage; StrMessage.Format (\当前时间是:%d 年%d 月%d 日
%d : %d : %d \ st.wYear, st.wMonth, st.wHour, st.wMinute, st.wSecond); MessageBox( StrMessage ); }
c) 将(1)中创建的三个文件:SysTime.h、SysTime.dll、SysTime.lib复制到本项目的
文件夹中,并将DLL文件在DEBUG文件夹中复制一份,这样直接启动应用程序时,也不会导致找不到动态链接库。 d) 运行并测试你的测试项目程序。
e) 现在请回答问题:动态链接库的隐式链接和显式链接的区别是什么? 2. MFC常规DLL编程练习:闰年判断程序
(1) 创建包含闰年判断函数的MFC常规DLL程序,创建步骤如下:
a) 新建MFC DLL项目,项目名称“RunNian”;
b) 在下图中,选择DLL类型为“使用共享MFC DLL的规则DLL”;
24
c) 现在你可以在项目中看到以下的文件: i. 预编译头 StdAfx.h, StdAfx.cpp ii. 资源文件Resource.h、Resource.cpp iii. 模板定义文件:RunNian.def,主要用来声明DLL的导出函数 iv. 主程序文件RunNian.h、RunNian.cpp d) 在文件RunNian.cpp的最后面添加以下代码:
BOOL IsRunNian(DWORD dwYear = 0)
{ AFX_MANAGE_STATE(AfxGetStaticModuleState());
//模式转化,确保切换到MFC模块mfc42.dll的状态下 BOOL Result = FALSE;
if(((dwYear%4==0)&&(dwYear!=0))||(dwYear@0==0)) { Result = TRUE; } return Result; }
e) 修改文件RunNian.def的代码,如下所示:
; RunNian.def : 声明DLL 的模块参数。 LIBRARY \
EXPORTS
; 此处可以是显式导出
IsRunNian @1
f) 编译并链接,此时将会同时产生RunNian.dll和RunNian.lib文件,后续程序可以使
用它们。
g) 现在请回答以下的问题: i. RunNian.def,模板定义文件的作用是什么? ii. RunNian.def中的“IsRunNian @1”,表示IsRunNian函数有哪几种调用方法?
(2) 创建使用闰年判断函数的MFC常规DLL程序的测试项目
a) 创建Win32控制台应用程序:RunNianCheck b) 修改RunNianCheck.cpp代码如下所示:
// RunNianCheck.cpp : 定义控制台应用程序的入口点。 #include \#include
int main(int argc, char* argv[]) { DWORD dwYear; //输入待判断的年份 printf(\输入年份!\\n\ scanf_s(\ HINSTANCE hInstance; //存储动态链接库的指针 typedef BOOL (FUN)(DWORD); //定义函数原型 FUN *pFun;
25
//给出具体路径,通过LoadLibrary函数加载 // 可以给出相对路径或者绝对路径 assert(hInstance = LoadLibrary(\
//通过GetProcAddress函数找到DLL中IsRunNian函数的指针 assert( pFun = (FUN*) GetProcAddress(hInstance, \ //通过IsRunNian函数的指针调用IsRunNian判断 if ( (*pFun)(dwYear) ) { printf(\是闰年!\ } else { printf(\不是闰年!\ } //使用FreeLibrary函数释放调用的DLL资源 assert(FreeLibrary(hInstance)); getchar(); getchar(); return 0; }
c) 运行此测试程序。
3. 创建COM组件编程练习:英文单词首字母变为大写 (1) 利用ATL创建COM组件“MyCom”,创建步骤如下:
a) 单击“文件”中的“新建”|“项目”,选择ATL项目,输入名称Mycom; b) 在下图中选择“服务器类型”为“动态连接库(DLL)” ,单击“完成”按钮。
c) 添加类: i. 在Mycom项目的“类视图”中右击Mycom,单击“添加类”。 ii. 在下图中选择“ATL简单对象”,单击“添加”按钮。
26
iii.
在下图中,输入“简称”(short name)为Str,确认类名为CStr,输入“CoClass”为“StrCom”,确认Prog ID为“Mycom.StrCom”,单击“下一步”。
iv.
在下图中选择相应的线程模型等,这里选择默认的选项。
d) 在COM组件中添加方法: i. 在“类视图”中,右击IStr接口,选择“添加方法”。
27
ii. iii.
输入方法名为“FirstToUpper” 添加三个参数分别为: [in] BSTR InData; [out] BSTR* OutData; [out,reval]long* result;
该方法的实现如下: // str.cpp
STDMETHODIMP CStr::FirstToUpper(BSTR InData, BSTR* OutData, long* result) { // TODO: 在此添加实现代码 CComBSTR strSource=InData;
bool bMayUpper=true; //是否可以大写的标志 for(int i=0;i
e) 编译IDL并注册COM组件: i. 设置项目属性为“Release”。 ii. 编译并链接ATL项目Mycom,你会在项目的Release目录中发现两个文件:
Mycom.tlb,接口定义文件对应的二进制文件 Mycom.dll
iii. 注册MyCom.dll:
要想让用户能够“透明”地使用创建的组件,首先必须将该组件注册。VC编译
28
iv.