题目:创建一个动态链接库,实现画一棵树。
1
).
启动Visual C++6.0
或者C++ Builder 5.0
.在WINDOWS98或WINDOWS 2000环境下,找到Visual C++6.0或者C++ Builder 5.0图标,双击之。为了不使Visual C++6.0或者C++ Builder 5.0的默认搜索路径与WINDOWS其他软件相冲突,清修改Visual C++6.0或者C++ Builder 5.0图标的属性。在属性|程序|批处理一栏中填上你自己的批处理程序名。以便启动时,首先运行你的批处理程序。然后在该批处理程序中,写上path=...路径。
2
).
设置用户程序子目录
设置用户程序子目录的目的是,将所有编程时产生的中间文件和最终执行程序文件全部
放在自己的目录中,以便管理。
3
).
创建和输入程序
Visual C++6.0启动后,要先建立一个project工程文件。方法为:
·选择File|new 菜单项,将弹出New 对话框。
·单击Projects 选项卡
·在Location中填用户子目录路径
·在Project name中填入工程名(如MyDll)
·在列表中选择MFC AppWizard(dll),表示你编制的应用程序将生成动态链接库文件(.dll)
·按照提示创建一个自己想要的工程
² 定位到mydll.h文件处,添加动态链接库的函数原型声明,下面为mydll.h的内容:
// MyDll.h : main header file for the MYDLL DLL
#include "resource.h"
// main symbols
/
// CMyDllApp
// See MyDll.cpp for the implementation of this class
//
int DrawTree(CPaintDC *dc,int xStart,int yStart,double length,double angle,int num);
class CMyDllApp : public CWinApp
{
public:
CMyDllApp();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyDllApp)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
//{{AFX_MSG(CMyDllApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
² 定位到mydll.cpp 文件处,添加动态链接库中的函数的实现部分,下面为mydll.cpp的内容:
// MyDll.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "MyDll.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// The one and only CMyDllApp object
CMyDllApp theApp;
int DrawTree(CPaintDC *dc,int xStart,int yStart,double length,double angle,
int num)
{
int xEnd,yEnd;
if (num==0) return 1;
xEnd=xStart+(int)(length*cos(angle));
yEnd=yStart+(int)(length*sin(angle));
dc->MoveTo(xStart,yStart);
dc->LineTo(xEnd,yEnd);
DrawTree(dc,xEnd,yEnd,length*0.6,angle+0.624,num-1);
DrawTree(dc,xEnd,yEnd,length*0.85,angle+0.08,num-1);
DrawTree(dc,xEnd,yEnd,length*0.65,angle-0.6,num-1);
return 1;
}
² 在mydll.def中引出DrawTree函数,下面为mydll.def的内容。
; MyDll.def : Declares the module parameters for the DLL.
LIBRARY
"MyDll"
DESCRIPTION 'MyDll Windows Dynamic Link Library'
EXPORTS
; Explicit exports can go here
DrawTree
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
l 编译程序
[
思考问题]
² 程序中大小写用错了,结果会怎样?
² 如果返回类型void没有,结果会怎样,是否需要return语句?
² 编译中若有警告信息,影响程序运行吗?
² 如何编写动态链接库文件以及步骤?
二
动态链接库文件的调用
1
、实验目的
(1) 解和掌握类和指向函数的指针的使用。
(2) 了解和掌握宏的使用。
(3) 掌握如何显示调用动态链接库文件。
(4) 掌握如何隐示调用动态链接库文件。
(5) 调用动态链接库文件的步骤。
2
、实验要求
熟练掌握在自己的应用程序中调用动态连接库文件的方法
3
、实验步骤与内容
1)
启动Visual C++6.0
或者C++ Builder 5.0
.在WINDOWS98或WINDOWS 2000环境下,找到Visual C++6.0或者C++ Builder 5.0图标,双击之。为了不使Visual C++6.0或者C++ Builder 5.0的默认搜索路径与WINDOWS其他软件相冲突,清修改Visual C++6.0或者C++ Builder 5.0图标的属性。在属性|程序|批处理一栏中填上你自己的批处理程序名。以便启动时,首先运行你的批处理程序。然后在该批处理程序中,写上path=...路径。
2
)设置用户程序子目录
设置用户程序子目录的目的是,将所有编程时产生的中间文件和最终执行程序文件全部
放在自己的目录中,以便管理。
3)创建和输入程序
Visual C++6.0启动后,要先建立一个project工程文件。方法为:
·选择File|new 菜单项,将弹出New 对话框。
·单击Projects 选项卡
·在Location中填用户子目录路径
·在Project name中填入工程名
·在列表中选择MFC AppWizard(exe),表示你编制的应用程序将生成可执行文件(.exe)
·按照提示创建一个自己想要的工程
4
)调用步骤
²
隐示链接
包含导出函数(或C++类)声明的头文件(.h)
导入库(.lib)文件
实际的DLL(.dll)文件
²
显示链接
显示链接时,使用DLL的可执行程序在运行时通过函数调用来显示加载或卸载
DLL,并通过函数指针来调用DLL的导出函数,要显示链接DLL,应用程序必须调用LoadLibrary来加载DLL,并获取模块句柄,调用GetProcAddress来获取应用程序要调用的导出函数的指针,使用完DLL后,应调用FreeLibrary来卸载DLL.
5
)主要程序代码
(1)定位到TestDllView.h文件处,添加函数原型声明,下面为TestDllView.h的内容:
// TestDllView.h : interface of the CTestDllView class
class CTestDllView : public CView
{
protected: // create from serialization only
CTestDllView();
DECLARE_DYNCREATE(CTestDllView)
// Attributes
public:
CTestDllDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestDllView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CTestDllView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CTestDllView)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in TestDllView.cpp
inline CTestDllDoc* CTestDllView::GetDocument()
{ return (CTestDllDoc*)m_pDocument; }
#endif
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TESTDLLVIEW_H__CFCBD8ED_D7AF_11D6_93F3_50784C6323E6__INCLUDED_)
(2)定位到视图类 CtestDllView的实现TestDllView.cpp中的函数OnPaint处,加入下列的代码:
void CTestDllView::OnPaint()
{
CPaintDC dc(this); // device context for painting
//
typedef int(*DRAWTREE)(CPaintDC *,int,int,double,double,
//
int);
typedef int(*DRAWTREE)(CPaintDC *,int,int,double,double,int);
DRAWTREE DrawTree;
CRect rect;
GetClientRect(rect);
FARPROC lpfn=NULL;
HINSTANCE hinst=NULL;
hinst=LoadLibrary("MyDll.dll");
if (hinst==NULL)
{
AfxMessageBox("不能加载动态链接库");
return;
}
lpfn=GetProcAddress(hinst,"DrawTree");
DrawTree=(DRAWTREE)lpfn;
dc.SetMapMode(MM_LOENGLISH) ;
if (lpfn==NULL)
AfxMessageBox("不能加载画树函数");
else
DrawTree(&dc,rect.right/2,-rect.bottom *9/10,(double)rect.bottom *0.2,1.57,9);
FreeLibrary(hinst);
// TODO: Add your message handler code here
// Do not call CView::OnPaint() for painting messages
}
6
)运行界面