第一篇:ADO编程总结(二)(小文档网整理)
ADO编程总结
(二)Connection,Recordset,Command对象都可以对数据库进行访问,并对数据库进行操作,以下是实验例程,由以下例程可见,读取数据库都要用到Recordset对象,而Recordset和command虽然都可以不需要connection对象而独自对数据库访问(例程在此为给出,可查我在《Visual c++6.0开发指南》上所夹的打印资料),但最方便的方法还是先用connection对象建立对数据库的连接,然后以此conection对象作为Recordset和command的open参数,打开数据库。
使用ConnectionPtr接口访数据库,并添加数据
1、创建_ConnetionPtr对象并实例化
2、调用Open方法访数据库
3、调用Execute方法,执行SQL命令
4、例程如下:
//1 建立连接
_ConnectionPtr pCon;
HRESULT hr;
try
{
hr=pCon.CreateInstance(_uuidof(Connection));
if(FAILED(hr))
{
AfxMessageBox(“Create Connection Instance Failed!”);
return;
}
pCon->ConnectionString=“File Name=mydata.udl”;
pCon->ConnectionTimeout=20;
hr=pCon->Open(“",”“,”“,adConnectUnspecified);
if(FAILED(hr))
{
AfxMessageBox(”Open Connection Failed!“);
return;
}
//2 利用Connection对象,为数据库添加数据CString strSQL=”insert into DVDData values(1006,'新闻联播','202_-2-12',3)“;COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);pRecordset=pCon->Execute(_bstr_t(strSQL),&vtOptional,-1);pCon.Release();} catch(_com_error e){bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());
} return;
使用RecordsetPtr接口访问数据库
1、创建_RecordsetPtr对象并实例化
2、调用Open方法访问数据库,数据源来自已建立连接的Connetcion对象
3、调用GetCollect方法获取数据库中的数据
4、例程如下:
_ConnectionPtr pCon;
_RecordsetPtr pRecordset;
HRESULT hr;
try
{
hr=pCon.CreateInstance(_uuidof(Connection));
if(FAILED(hr))
{
AfxMessageBox(”Create Connection Instance Failed!“);
return;
}
pCon->ConnectionString=”File Name=mydata.udl“;
pCon->ConnectionTimeout=20;
hr=pCon->Open(”“,”“,”“,adConnectUnspecified);
if(FAILED(hr))
{
AfxMessageBox(”Open Connection Failed!“);
return;
}
//2 利用Recordset对象,读取数据库数据
hr=pRecordset.CreateInstance(_uuidof(Recordset));
if(FAILED(hr))
{
AfxMessageBox(”Create Recordset Instance Failed!“);
return;
}
CString strSQL=”select * from DVDData“;
hr=pRecordset->Open(_variant_t(strSQL),pCon.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);if(FAILED(hr))
{
AfxMessageBox(”Open Recordset Failed!“);
return;
}
_variant_t var;CString strValue;while(!pRecordset->rsEOF){c=m_datalist.GetItemCount();var=pRecordset->GetCollect(”编号“);if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_datalist.InsertItem(c,strValue);var=pRecordset->GetCollect(”名称“);if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_datalist.SetItemText(c,1,strValue);
var=pRecordset->GetCollect(”日期“);
if(var.vt!=VT_NULL)
strValue=(LPCSTR)_bstr_t(var);
m_datalist.SetItemText(c,2,strValue);
var=pRecordset->GetCollect(”数目“);
if(var.vt!=VT_NULL)
strValue=(LPCSTR)_bstr_t(var);
m_datalist.SetItemText(c,3,strValue);
pRecordset->MoveNext();
}
}
catch(_com_error e)
{
bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
AfxMessageBox(bstrSource+bstrDescription);
return;
}
pRecordset->Close();
pRecordset=NULL;
pCon.Release();
5、为数据库添加数据
pRecordset->AddNew();
CString strNum;
strNum.Format(”%d“,m_number);
pRecordset->PutCollect(”编号“,_variant_t(strNum));
pRecordset->PutCollect(”名称“,_variant_t(m_name));pRecordset->PutCollect(”日期“,_variant_t(m_date));pRecordset->PutCollect(”数目“,_variant_t(m_count));pRecordset->Update();
使用Command对象打开数据库
1、定义_CommandPtr、_RecordsetPtr对象实例化_CommandPtr对象
2、使用Execute方法执行SQL命令,返回结果保存在Recordset对象中。
3、使用RecordsetPtr的GetCollect方法获取数据
4、例程如下:
_CommandPtr pCommand;
_RecordsetPtr pRecordset;
_ConnectionPtr pCon;
HRESULT hr;
try
{
hr=pCon.CreateInstance(_uuidof(Connection));
if(FAILED(hr))
{
AfxMessageBox(”Create Connection Instance Failed!“);return;
}
pCon->ConnectionString=”File Name=mydata.udl“;
pCon->ConnectionTimeout=20;
hr=pCon->Open(”“,”“,”“,adConnectUnspecified);
if(FAILED(hr))
{
AfxMessageBox(”Open Connection Failed!“);
return;
}
pCommand.CreateInstance(_uuidof(Command));
pCommand->ActiveConnection=pCon;
pCommand->CommandText=”select * from DVDData“;
pCommand->Parameters->Refresh();
pRecordset=pCommand->Execute(NULL,NULL,adCmdText);
int c;
_variant_t var;
CString strValue;
while(!pRecordset->rsEOF)
{
c=m_datalist.GetItemCount();
var=pRecordset->GetCollect(”编号“);
}if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_datalist.InsertItem(c,strValue);var=pRecordset->GetCollect(”名称“);if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_datalist.SetItemText(c,1,strValue);var=pRecordset->GetCollect(”日期“);if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_datalist.SetItemText(c,2,strValue);var=pRecordset->GetCollect(”数目");if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_datalist.SetItemText(c,3,strValue);pRecordset->MoveNext();} } catch(_com_error e){bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());AfxMessageBox(bstrSource+bstrDescription);return;} pRecordset->Close();pRecordset=NULL;pCon.Release();
第二篇:ADO编程总结(一)
ADO编程总结
(一)1、在stdafx.h中添加代码:
#import “C:Program FilesCommon FilesSystemadomsado15.dll” no_namespace rename(“EOF”,“rsEOF”)
2、在APP.cpp的InitInstance中加入: ::CoInitialize(NULL);在ExitInstance()中加入:
::CoUninitialize();
3、工程目录下用记事本新建一文件,另存为扩展名为.udl的文件,如这里保存为mydata.udl,双击出现数据链接属性对话框,参考下图进行设置,确定。
4、定义以下变量:
_ConnectionPtr m_pConnection;_RecordsetPtr m_pRecordset;
5、初始化连接函数
BOOL CADOTestDlg::InitConnection(){ HRESULT hr;try
{
①hr=m_pConnection.CreateInstance(_uuidof(Connection));
if(SUCCEEDED(hr))
{
②m_pConnection->ConnectionString=“File Name=mydata.udl”;
m_pConnection->ConnectionTimeout=20;
hr=m_pConnection->Open(“",”“,”“,adConnectUnspecified);
if(FAILED(hr))
{
AfxMessageBox(_T(”打开连接失败“));
return FALSE;
}
}
else
{
AfxMessageBox(_T(”实例化连接失败“));
return FALSE;
}
return TRUE;} catch(_com_error e){
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
AfxMessageBox(bstrSource+bstrDescription);
return FALSE;} } 对以上程序主要结果是一个try catch语句,其中 ①hr=m_pConnection.CreateInstance(_uuidof(Connection));实例化连接对象,固定格式 ②m_pConnection->ConnectionString=”File Name=mydata.udl“;设置连接串属性为UDL文件
m_pConnection->ConnectionTimeout=20;连接等待时间为20秒
hr=m_pConnection->Open(”“,”“,”“,adConnectUnspecified);使用Connection对象打开连接,其中adConnectUnspecified表示同步模式,若为adAsyncConnect表示异步模式。
该函数是比较固定,可以在以后的应用中复制经少量修改即可应用。
6、查询数据库表中的信息并输出:
void CADOTestDlg::OnBnClickedBtnShowAll(){ HRESULT hr;①_RecordsetPtr pShowAllRecordset;hr=pShowAllRecordset.CreateInstance(_uuidof(Recordset));if(FAILED(hr)){
AfxMessageBox(_T(”Create Instance of Recordset failed!“));return;} CString strSql;_variant_t var;CString strValue;int curItem=0;strSql=_T(”select * from emp“);try { ②hr=pShowAllRecordset->Open(_variant_t(strSql),m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);if(SUCCEEDED(hr)){
③while(!pShowAllRecordset->rsEOF)
{
curItem=m_DataList.GetItemCount();
④var=pShowAllRecordset->GetCollect(_T(”EMPNO“));
if(var.vt!=VT_NULL)
strValue=(LPCSTR)_bstr_t(var);
m_DataList.InsertItem(curItem,strValue);
var=pShowAllRecordset->GetCollect(_T(”ename“));if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_DataList.SetItemText(curItem,1,strValue);var=pShowAllRecordset->GetCollect(_T(”hiredate“));if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_DataList.SetItemText(curItem,2,strValue);var=pShowAllRecordset->GetCollect(_T(”sal“));if(var.vt!=VT_NULL)strValue=(LPCSTR)_bstr_t(var);m_DataList.SetItemText(curItem,3,strValue);var=pShowAllRecordset->GetCollect(_T(”comm“));if(var.vt!=VT_NULL)
strValue=(LPCSTR)_bstr_t(var);
m_DataList.SetItemText(curItem,4,strValue);
⑤pShowAllRecordset->MoveNext();
}
} } catch(_com_error* e){
AfxMessageBox(e->ErrorMessage());
return;} ⑥pShowAllRecordset->Close();pShowAllRecordset=NULL;} 该函数也比较固定,通过设置命令文本字符串,对数据库进行操作,主要有以下几步 ①_RecordsetPtr pShowAllRecordset;hr=pShowAllRecordset.CreateInstance(_uuidof(Recordset));定义Recordset对象,并实例化,格式固定。②hr=pShowAllRecordset->Open(_variant_t(strSql),m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);尝试打开记录,其中Open函数参数意义如下:
第1个参数:记录源,可以是下列内容之一:Command对象变量,SQL语句,存储过程,表名或完整的路径名,这里是命令文本,一般也是用命令文本。
第2个参数:指定在哪个连接中打开记录集。m_pConnection.GetInterfacePtr():Returns the encapsulated interface pointer,返回封闭接口指针,不懂。
第3、4个参数:详细说明见《Visual C++6.0 开发指南》714,715页,不懂。第5个参数:表示第1个参数的各类,这里是adCmdText,表示命令文本,其它取值见《Visual C++6.0 开发指南》715页。③while(!pShowAllRecordset->rsEOF)循环。
当记录未到末尾时,执行循环,这里有可能会报错:
: “rsEOF”: 不是“_Recordset”的成员
请确认在stdafx.h中添加了以下代码:rename(”EOF“,”rsEOF“)var=pShowAllRecordset->GetCollect(_T(”EMPNO“));
if(var.vt!=VT_NULL)
strValue=(LPCSTR)_bstr_t(var);
m_DataList.InsertItem(curItem,strValue);④var=pShowAllRecordset->GetCollect(_T(”EMPNO“));
if(var.vt!=VT_NULL)
strValue=(LPCSTR)_bstr_t(var);
m_DataList.InsertItem(curItem,strValue);比较固定的结构,从记录中读取列名为”EMPNO"的数据,保存到var结构中,再转换到CString对象。
数据类型的转换:
COM中的VARIANT、BSTR两种数据类型与C++中CStrng类型的转换分别通过两个类来实现: _variant_t 和_bstr_t。⑤pShowAllRecordset->MoveNext();记录指针向前移动。⑥pShowAllRecordset->Close();pShowAllRecordset=NULL;关闭记录对象。
第三篇:ADO编程模型之VB数据库操作小结
ADO编程模型之VB数据库操作小结
使用ADO编程模型需添加ADO对象类库的“引用”----“Microsoft ActiveX Data Objects 2.x Library” ADO之VB数据库操作主要包括读、写、修改及删除等操作,不论是进行什么数据库操作都必须首先连接到数据库。
一、连接到数据库
1、连接到SQL数据库:
通过ADO的Connection对象可实现VB与SQL数据库的连接。一般方法如下:
Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象
cnn.ConnectionString = “Provider=SQLOLEDB.1;Password=密码;User ID=用户名;Initial Catalog=SQL数据库文件;Data Source= localhost;”
'指定提供者,设置数据源 cnn.Open
‘打开到数据库的连接 ……..cnn.Close
‘关闭到数据库的连接 或者:
Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象
cnn.Open “Provider=SQLOLEDB.1;Password=密码;User ID=用户名;Initial Catalog=SQL数据库文件;Data Source= localhost;”
‘打开到数据库的连接 ……..cnn.Close
‘关闭到数据库的连接
2、连接到ACCESS数据库:
通过ADO的Connection对象可实现VB与ACCESS数据库的连接。一般方法如下:
Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象
cnn.ConnectionString = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=ACCESS数据库文件.MDB” '指定提供者,设置数据源
cnn.Open
‘打开到数据库的连接 ……..cnn.Close
‘关闭到数据库的连接 或者: Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB”
‘打开到数据库的连接 ……..cnn.Close
‘关闭到数据库的连接
二、读数据库操作
读数据库操作一般可通过recordset对象实现。方法如下—以ACCESS数据库为例:
Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB”
‘打开到数据库的连接
Dim rs As New Recordset
'声明一个记录集对象
rs.Open [记录源, cnn, 游标类型, 锁定类型, 命令类型]
‘也可先设置记录集相关属性
text1.text= rs(“字段名称1或索引”)
‘假设读取出来的字段信息显示在文本框中,三种读取方法等价 text2.text=rs.fields(“字段名称2或索引”)text3.text= rs!字段名称3 …….rs.close
‘关闭记录集对象 cnn.Close
‘关闭与数据库的连接 set rs=Nothing
‘释放rs对象实例 set cnn=Nothing ‘释放Connection对象实例
记录源一般为一条SQL查询语句,以实现查询目的。
Recordset对象还保持查询返回的记录的位置,它返回第一个检索到的记录,并允许你一次一项逐步扫描其他结果。Recordset对象的部分属性及方法如下 Rs(i): 读取第i个字段的数据,i从0开始 Rs(字段名): 读取指定字段的数据 Rs.EOF:记录指针指到记录的尾部 Rs.BOF:记录指针指到记录的头部 Rs.RecordCount: 游标中的数据记录总数
Rs.PageSize:当对象设有分页时,用于指定逻辑页中的记录个数 Rs.PageCount:返回记录集中的逻辑分页数 Rs.MoveNext: 将记录指针移到下一个记录 Rs.MovePrev: 将记录指针移到上一个记录 Rs.MoveFirst: 将记录指针移到第一个记录 Rs.MoveLast: 将记录指针移到最后一个记录 rs.Delete:将当前记录删除 rs.addnew:添加一条新记录(行)
如果要读取满足条件的数据库记录,只要在SELECT语句中增加WHERE子句即可(例如:WHERE 性别=”男”),如果要读取多条满足条件的数据库记录,可通过循环语句来实现,并且每读取一条记录后使用Rs.MoveNext移动记录指针以读取下一条记录。
三、写数据库操作
方法1:使用recordset对象(此方法一般初学者使用较多)。方法如下—以ACCESS数据库为例: Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB”
‘打开到数据库的连接
Dim rs As New Recordset
'声明一个记录集对象
rs.Open [记录源, cnn, 游标类型, 锁定类型, 命令类型]
‘也可先设置记录集相关属性 rs.addnew ‘告诉rs我们要添加一行
rs(“字段名称1或索引”)=值1
‘给要添加的行的一个字段赋值,三种方法等价 rs.fields(“字段名称2或索引”)=值2 rs!字段名称3 =值3 …….rs.update
‘通知rs我们要把这个行写入数据库 rs.close
‘关闭记录集对象 cnn.Close
‘关闭与数据库的连接 set rs=Nothing
‘释放rs对象实例 set cnn=Nothing ‘释放Connection对象实例
addnew使用方法后,如果要放弃添加的结果,应调用记录集的CancelUpdate方法放弃。
方法2:使用Connection对象的Execute方法对表进行SQL记录插入操作(要求要熟悉SQL命令)Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB”
‘打开到数据库的连接
strSQL = “Insert Into 数据表(字段1, 字段2…..)Values(值1, 值2…..)
‘拼写Insert插入语句 cnn.Execute strSQL
'执行Insert语句实现添加 …….cnn.Close
‘关闭与数据库的连接
set cnn=Nothing ‘释放Connection对象实例
四、修改数据库操作
方法1:使用recordset对象(此方法一般初学者使用较多)。方法如下—以ACCESS数据库为例: Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB“
‘打开到数据库的连接
Dim rs As New Recordset
'声明一个记录集对象
rs.Open [记录源, cnn, 游标类型, 锁定类型, 命令类型]
‘也可先设置记录集相关属性 …….rs(”字段名称1或索引“)=新值1
‘‘给要修改的行的一个字段赋一个新值,三种方法等价 rs.fields(”字段名称2或索引“)=新值2 rs!字段名称3 =新值3 …….rs.update
‘通知rs,我们要把修改好的记录行写入数据库 rs.close
‘关闭记录集对象 cnn.Close
‘关闭与数据库的连接 set rs=Nothing
‘释放rs对象实例 set cnn=Nothing ‘释放Connection对象实例
如果放弃修改结果,应调用记录集的CancelUpdate方法放弃更新数据库。
方法2:使用Connection对象的Execute方法对表进行SQL记录更新操作(要求要熟悉SQL命令)Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB“
‘打开到数据库的连接
strSQL = ”Update 数据表 Set 字段1=新值1, 字段2=新值2…..‘拼写Update语句,以便进行修改 cnn.Execute strSQL
'执行Insert语句实现添加 …….cnn.Close
‘关闭与数据库的连接
set cnn=Nothing ‘释放Connection对象实例
五、删除数据库操作
方法1:使用recordset对象(此方法一般初学者使用较多)。方法如下—以ACCESS数据库为例方法1:通过 Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB”
‘打开到数据库的连接
Dim rs As New Recordset
'声明一个记录集对象
rs.Open [记录源, cnn, 游标类型, 锁定类型, 命令类型]
‘也可先设置记录集相关属性 …….rs.Delete
‘删除当前记录 …….rs.update
‘通知rs,我们要把修改好的记录行写入数据库 rs.close
‘关闭记录集对象 cnn.Close
‘关闭与数据库的连接 set rs=Nothing
‘释放rs对象实例 set cnn=Nothing ‘释放Connection对象实例
删除数据库记录前应先找到(查询)待删除的记录项(通过rs.Open来实现)。
方法2:使用Connection对象的Execute方法(要求使用者要熟悉SQL命令)例如:如果要将数据库“成绩.mdb”中的名字为“学生情况表”的数据表中,学号为'07001'的记录删除,可通过下列方法来实现。
Dim cnn As New ADODB.Connection ‘创建Connection对象cnn,关键字new用于创建新对象 cnn.Open “Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=ACCESS
数据库文件.MDB”
‘打开到数据库的连接
sql=“delete from学生情况表where 学号='07001'”
‘拼写delete语句,以便进行删除
cnn.Execute strSQL
'执行elete语句实现删除 …….cnn.Close
‘关闭与数据库的连接
set cnn=Nothing ‘释放Connection对象实例
附:分页简介---使用记录集
一、.原理:
分页其实是将数据库中的记录分割成若干段,并将各段记录放在同一个“逻辑页面”上“分屏显示”出来,其实显示的“逻辑页面”只有1页,只是每次显示的页面记录不同罢了。通过控制各页中数据库显示记录的不同,来刷新页面的显示内容。
二、用到的几个记录集属性
rs.pagesize:定义一页显示记录的条数; rs.recordcount:统计数据库记录总数; rs.pagecount:统计总页数;
rs.absolutepage:将数据库指针移动到当前页要显示的数据记录的第一条记录;比如有20条记录的一个数据库,我们分为一页显示5条记录,如将AbsolutePage属性设为2,则当前记录指针移至第2页第1条记录,也即将指针移动到第6条记录处,依次类推....(AbsolutePage 属性是以 1 为起始的)
第四篇:MFC编程讲稿(二)
一、打字功能
1.加入数据成员
选择ClassView,双击CMyView,光标直接停留在类CMyView的定义处。在类CMyView中加入如下部分: class CMyView : public CView { protected: // create from serialization only
CMyView();
DECLARE_DYNCREATE(CMyView)
// Attributes public:
CMyDoc* GetDocument();
// Operations public: //代码编写开始
POINT Caret;
//用于存放插入符当前坐标位置 //代码编写结束 // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyView)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 ~CMyView();#ifdef _DEBUG virtual void AssertValid()const;virtual void Dump(CDumpContext& dc)const;#endif
protected:
// Generated message map functions protected: //{{AFX_MSG(CMyView)afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);//}}AFX_MSG DECLARE_MESSAGE_MAP()};2.加入消息:WM_CREATE(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。
(2)选择 Message Maps。(3)分别选择:
Project: 打字
Class Name: CMyView Objects: CMyView Messges: WM_CREATE(4)单击Add Function按钮。
(5)单击Edit Code按钮。在OnCreate()函数体中加入以下部分。
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct){ if(CView::OnCreate(lpCreateStruct)==-1)
return-1;//代码编写开始
TEXTMETRIC tm;
//声明TEXTMETRIC结构类型对象tm,用于存放字符信息。
CClientDC dc(this);
//生成应用程序窗口设备情景对象
//调用CDC类成员函数GetTextMetrics()取得字符信息,并存入变量tm中。
dc.GetTextMetrics(&tm);//调用CWnd类成员函数CreateSolidCaret()创建黑色矩形条插入符,插入符宽度为tm.tmAveCharWidth/8,高度为tm.tmHeight。
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);//设置插入符的初始位置
Caret.x=0;
} Caret.y=tm.tmHeight;SetCaretPos(Caret);//在初始位置显示插入符 ShowCaret();//代码编写结束 return 0;3.加入键盘消息:WM_CHAR(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。
(2)选择 Message Maps。(3)分别选择:
Project: 打字
Class Name: CMyView Objects: CMyView Messges: WM_CHAR(4)单击Add Function按钮。
(5)单击Edit Code按钮。在OnChar()函数体中加入以下部分。
void CMyView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){
// TODO: Add your message handler code here and/or call default
//代码编写开始
SIZE size;
//存放字符的宽度和长度。
static UINT dy=Caret.y;
//声明静态变量dy,存放插入符Y轴坐标。CString a;
//声明CString类对象a,存放键盘检索到的字符nChar。a=nChar;CClientDC dc(this);//生成应用程序窗口设备情景对象
} CView::OnChar(nChar, nRepCnt, nFlags);for(UINT i=0;i } //代码编写结束 HideCaret(); //隐藏光标,使得显示字符使插入符消失。switch(nChar){ case 'r': //将插入符移动到下一行的开头 Caret.x=0;Caret.y+=Caret.y;break;default: } //将插入符移动到字符后面,并显示出来。SetCaretPos(Caret);ShowCaret();dc.TextOut(Caret.x,Caret.y,a,1);//输出字符 size=dc.GetTextExtent(a);//获得字符大小 Caret.x+=size.cx;//将字符的宽度加入到插入符的当前坐标位置 二、绘图功能 (一)生成Draw程序框架 (二)鼠标绘图 用鼠标绘制图形,一般分三个环节: (1)确定绘图位置:按下鼠标左键,产生WM_LBUTTONDOWN消息(2)确定图形显示范围:拖动鼠标,产生WM_MOUSEMOVE消息(3)完成图形显示:放开鼠标左键,产生WM_LBUTTONUP消息 1.在视图类CDrawView中加入数据成员 选择ClassView视图,双击CdrawView,光标直接停留在类CdrawView的定义处。在类CdrawView的定义中加入如下代码。 class CDrawView : public CView { //代码开始编写 protected: int m_Dragging; CPoint m_PointOld;CPoint m_PointOrigin;//代码编写结束 protected: // create from serialization only // Attributes public: // Operations CDrawView();DECLARE_DYNCREATE(CDrawView)CDrawDoc* GetDocument();public: // Overrides // Implementation public: virtual ~CDrawView();// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CDrawView)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 #ifdef _DEBUG virtual void AssertValid()const;virtual void Dump(CDumpContext& dc)const;#endif protected: // Generated message map functions protected: //{{AFX_MSG(CDrawView)// NOTEthe 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()21 4.定义函数CdrawDoc::AddLine()选择FileView,展开SourceFiles,双击DrawDoc.cpp,打开执行文件DrawDoc.cpp,在其末尾,加入以下代码。 //代码编写开始 // AddLine()生成新的Cline对象,并调用CObArray成员函数Add()向m_LineArray添加Cline对象指针。 void CDrawDoc::AddLine(int X1,int Y1,int X2,int Y2){ } //代码编写结束 CLine *pLine=new CLine(X1,Y1,X2,Y2);m_LineArray.Add(pLine);5.定义函数CdrawDoc::GetLine()选择FileView,展开SourceFiles,双击DrawDoc.cpp,打开执行文件DrawDoc.cpp,在其末尾,加入以下代码。 //代码编写开始 // CObArray成员函数GetUpperBound()返回加入的最后一个指针的索引,即最大的有效索引,CObArray成员函数GetAt()返回对应的CLine指针。如果索引号小于0或大于最大的有效索引号,GetLine()返回0;否则,返回对应的CLine指针。 CLine *CDrawDoc::GetLine(int Index){ } //代码编写结束 if(Index<0||Index>m_LineArray.GetUpperBound())return 0;return(CLine *)m_LineArray.GetAt(Index);22 6.定义函数CdrawDoc::GetNumLines()选择FileView,展开SourceFiles,双击DrawDoc.cpp,打开执行文件DrawDoc.cpp,在其末尾,加入以下代码。 //代码编写开始 // 通过调用CObArray成员函数GetSize(),GetNumLines()返回m_LineArray当前存放的CLine指针的个数。 int CDrawDoc::GetNumLines(){ } //代码编写结束 return m_LineArray.GetSize();7.修改函数视图类消息处理函数OnLButtonUp()调用GetDocument()和AddLine()来存放新直线。 回到Workspace,选择ClassView,单击CDrawView,展开CdrawView成员变量和成员函数。双击OnLButtonUp(),在函数OnLButtonUp()中定义后加入以下代码。 void CDrawView::OnLButtonUp(UINT nFlags, CPoint point){ // TODO: Add your message handler code here and/or call default int b; CRect Rect(40,40,600,400);b=Rect.PtInRect(point);if(b)::SetCursor(m_HCross);else ::SetCursor(m_HArrow);if(m_Dragging&&b){ m_Dragging=0;CClientDC dc(this);dc.SetROP2(R2_NOT); dc.MoveTo(m_PointOrigin);dc.LineTo(m_PointOld);dc.MoveTo(m_PointOrigin);dc.LineTo(point);//代码开始编写 //调用函数GetDocument()取得文档类的指针,并存入pDoc中。CDrawDoc * pDoc=GetDocument(); //通过指针pDoc调用加入的文档类成员函数AddLine()向m_LineArray加入 Cline类直线对象。 pDoc->AddLine(m_PointOrigin.x,m_PointOrigin.y,point.x,point.y); // 当一条新的直线绘制完成,视图类OnLButtonUp(nFlags, point)函数通过上面的工作将新绘制的直线存入文档类中。 } } CView::OnLButtonUp(nFlags, point);//代码编写结束 8.修改视图类成员函数OnDraw()void CDrawView::OnDraw(CDC* pDC){ CDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data here pDC->MoveTo(40,40); pDC->LineTo(600,40); pDC->LineTo(600,400); pDC->LineTo(40,400); pDC->LineTo(40,40); //代码编写结束 } 9.编译、运行 //代码开始编写 int Index=pDoc->GetNumLines();while(Index--)pDoc->GetLine(Index)->Draw(pDC); (六)图形的删除 下面向Draw程序加入图形的编辑功能。选择“编辑/撤销”菜单命令就可以删除最近绘制的直线,选择“编辑/全部删除”菜单命令可以清除掉视图窗口中所有的直线。 函数DeleteContents专门负责文档数据的删除工作,可以在文档类中加入该函数删除存放的直线。我们的目的是通过菜单命令答道编辑的功能,因此需要加入“编辑/撤销”和 “编辑/全部删除”菜单命令的消息处理函数,在它们的消息处理函数中调用函数DeleteContents()。 1. 加入“编辑”菜单命令“全部删除” (1)选择ResourceView视图,打开Menu项目下的IDR_MAINFRAME标志符,在Edit菜单下面加入菜单命令 “全部删除”。 ID标志符为:ID_EDIT_CLEAR_ALL,Caption为:全部删除(&A)tCtrl+A(2)双击Accelerator项目下面的IDR_MAINFRAME标志符,打开快捷键编辑器。双击快捷键编辑框底部的空框,在ID文本框中输入ID_EDIT_CLEAR_ALL,在Key文本框中输入A,并选择Ctrl。 2. 加入虚函数DeleteContents()25(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects: CDrawDoc Messges: DeleteContents(4)单击Add Function按钮。 (5)单击Edit Code按钮。在DeleteContents()函数体中加入以下部分。void CDrawDoc::DeleteContents(){ } 3. 加入ID_EDIT_CLEAR_ALL的COMMAND消息处理函数OnEditClearAll()(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_CLEAR_ALL Messges: COMMAND // TODO: Add your specialized code here and/or call the base class //代码编写开始 int Index=m_LineArray.GetSize();while(Index--)delete m_LineArray.GetAt(Index);m_LineArray.RemoveAll();//代码编写结束 CDocument::DeleteContents();(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnEditClearAll()函数体中加入以下部分。void CDrawDoc::OnEditClearAll(){ // TODO: Add your command handler code here //代码编写开始 DeleteContents(); } 4. 加入ID_EDIT_CLEAR_ALL的UPDATE_COMMAND_UI消息处理函数(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_CLEAR_ALL Messges: UPDATE_COMMAND_UI(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnUpdateEditClearAll()函数体中加入以下部分。void CDrawDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI){ } 5. 加入ID_EDIT_UNDO的COMMAND消息处理函数 UpdateAllViews(0);//代码编写结束 // TODO: Add your command update UI handler code here //代码编写开始 pCmdUI->Enable(m_LineArray.GetSize());//代码编写结束(1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_UNDO Messges: COMMAND(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnEditUndo()函数体中加入以下部分。void CDrawDoc::OnEditUndo(){ // TODO: Add your command handler code here //代码编写开始 int Index=m_LineArray.GetUpperBound(); } 6. 加入ID_EDIT_UNDO的UPDATE_COMMAND_UI消息处理函数 (1)在“查看”菜单中选择“建立类向导”(ClassWizard)命令,打开MFC ClassWizard窗口。 (2)选择 Message Maps。(3)分别选择: Project: Draw Class Name: CDrawDoc Objects IDs: ID_EDIT_UNDO if(Index>-1){ } UpdateAllViews(0);//代码编写结束 delete m_LineArray.GetAt(Index);m_LineArray.RemoveAt(Index);Messges: UPDATE_COMMAND_UI(4)单击Add Function按钮。 (5)单击Edit Code按钮。在OnUpdateEditUndo()函数体中加入以下部分。void CDrawDoc::OnUpdateEditUndo(CCmdUI* pCmdUI){ // TODO: Add your command update UI handler code here //代码编写开始 pCmdUI->Enable(m_LineArray.GetSize());//代码编写结束 } (七)图形的存取 (八)滚动窗口 (九)分割窗口 (十)拖放与注册 Mudos编程总结 1,Mudos系统调用系统 MudLib系统文件 的过程和一些特点 Mudos启动以后先要寻找一个配置文件,用来配置MudLib文件系统的一些信息(这里时config.cfg),找不到就无法启动。找到以后根据配置文件里面的参数进行初始化Mudos,然后调用配置文件里面的两个入口文件,即simul_efun.c和master.c。首先载入simul_efun文件并生成一个特殊的全局对象,这个对象用于定义一些全局使用的函数,也可以重载Mudos中的Efun函数,这些新定义的文件使用起来和Efun是一样的。然后系统会调用master.c文件并生成一个全局对象(主控对象),主控对象用于系统的全局控制,包括全局对象的加载,错误信息的跟踪处理等。接下来,系统会根据主控对象中的定义,载入一些系统需要用到的全局对象。到此,Mudos系统就启动完成了。 2、用户连接系统后的处理过程。。 当用户通过客户端进行连接以后,Mudos系统会调用master对象特有的connect()函数,通过这个函数编程人员需要创建并返回一个用户对象,系统会将用户连接到这个用户对象上,即是说这个用户对象就代表了这个用户。到此,就算完成了用户的连接过程。 3、用户的登陆后的处理过程 当Mudos系统调用master的connect函数创建并返回一个用户对象以后,用户对象会调用特有的logon()函数,这个函数用来把用户的设置都设置好并进行游戏。注:最好在这里重新建立一个用户对象,然后通过exec函数把用户的连接转移到新的对象上,然后删除这个对象。 4、Mudos系统中的系统中 对象 simul_efun对象、master主控对象和用户对象这三种对象都是系统提供的特殊对象,其 中simul_efun对象和master主控对象在系统中只有一个实例,即不能被clone也不能new创建,而用户对象主要的作用就是用来创建用户并完成初始化的对象,用户每次登陆都会自动生成一个,用户登陆完成后最好删除它。这里需要指出主控对象和用户对象都有特有的一些函数,这些函数提供给Mudos系统来调用的,用来完成一些系统需要处理的事情。 5、Master主控对象 object connect()程序连接后调用的函数,创建并返回一个用户对象。string *epilog(int load_empty)返回一个包含物件文件名称的数组, 其中所有的文件为启动游戏之前必须预先载入的对象.void preload(string file)系统按照epilog函数返回的数组载入全局对象后调用次函数,用来判断对象是否成功创建 static void crash(string error, object command_giver, object current_object)当系统异常终止(crash)时, 就调用主控物件中的此函数,用来记录一些系统crash的log信息。void log_error(string file, string message)编译程序发生任何错误系统都会调用此函数,用于发现是哪个对象出了什么错误。用于记录编译程序时出现的错误信息。 string error_handler(mapping error, int caught)主控物件处理错误的函数,此函数让 mudlib 代替系统处理错误情形。用来处理系统运行时出现的错误信息。string get_root_uid()取得 root 使用者识别名称需要获取系统的uid时调用此函数。string get_bb_uid()取得骨架使用者识别名称。string creator_file(string str)系统创建任何对象时都会调用此函数,用来获得系统初始化对象的uid值。mixed compile_object(string file)提供虚拟对象,当系统无法按照给定的路径载入对象时调用此函数。如果返回值是0,系统将不会载入这个对象,如果返回值是一个对象,系统会把这个对象当作是系统要载入的对象。一般来说,这里会返回一个void对象。string object_name(object ob)系统调用此函数以知晓一个物件的名称。string domain_file(string str)返回一个指定对象所属的区域,系统调用此函数来获得对象的区域。string author_file(string str)返回一个指定对象所属的作者,系统调用此函数来获得对象的作者。int save_ed_setup(object who, int code)ed()函数储存一个使用者的编辑程序设定或组态设定时调用 int retrieve_ed_setup(object who)ed()函数取得使用者的编辑程序设定或组态设定 string make_path_absolute(string file)ed()函数调用此函数以转换文件的相对路径名称为绝对路径名称 string get_save_file_name(string fname)ed()函数使用者不正常断线时, 此函数应返回与原来文件不同的名称, 以免覆写原来的文件 string privs_file(string file)为新创造的对象指定一个私有字符串。创建任何对象时系统都会调用此函数.对象的文件名称为其参数,返回的字符串就用作此对象的私有字符串。void slow_shutdown(int minutes)告知 mud 目前正处于缓慢关闭的过程中.当系统无法从堆中配置更多的内存, 而只能使用保留的内存区块时, 主控物件会调用此函数.此函数只有在组态文件中设定了「内存区块保留大小」才会被调用.距离关闭时间还剩下几分钟则为此函数的参数.void flag(string)当系统启动时, 处理 mudlib 所指定的特定标志.这个函数暂时还不是很了解。int valid_override(string file, string name)是否允许使用 efun:: 的情形,即是否允许运行efun重载前的函数。int valid_seteuid(object ob, string str)是否允许设定一个对象的euid。int valid_socket(object eff_user, string fun, mixed *info)是否允许调用socket 外部函数 int valid_asm(string file) 是否能使用asm{}来控制 LPC->C 编译的物件 int valid_compile_to_c(string file)是否允许由 LPC->C 的方式编译 int valid_hide(object who)是否允许一个对象具有匿踪和看到匿踪对象的能力 int valid_object(object ob)是否允许载入某个对象。int valid_save_binary(string filename)是否允许一个对象储存它的源代码 int valid_bind(object binder, object old_owner, object new_owner)是否允许bind()函数 即把某个对象的函数指针指向其他对象。int valid_write(string file, mixed user, string func)是否允许一个人有权限写入一个文件 int valid_read(string file, mixed user, string func)是否允许一个人有权限读取一个文件 int valid_shadow(object ob)控制哪些对象可以作为投影。int valid_link(string original, string reference)是否允许link()函数 int view_errors(object user)是否允许一个使用者看到错误消息 int valid_compile(string file)是否允许预先编译文件,这是22.2b14新加的设置6、、、、用户对象 void logon()主控对象conncet函数返回的用户对象会直接调用次函数,用以对用户对象的初始化处理。string process_input(string str)用户输入信息后调用此函数,字符串处理后再传递给本用户对象,用来处理用户输入信息。void net_dead()当用户对象断线时, 系统调用此函数。用来处理用户断线后的事情。void terminal_type(string term_type)用户对象登陆后调用,获得用户登陆的终端型号。void receive_message(string type, string str)用户对象的消息处理函数,系统的message()函数会把消息分配给各个符合条件的用户对象,用户对象接收到消息后调用此函数来接收并处理消息。void catch_tell(string message);无论系统对 一个对象送出任何消息都会调用此函数来处理这些消息.消息可以依照需要显示、丢弃、修改.此函数可以当作耳罩挡住某些消息, 也可以用于消息处理程序.void receive_snoop(string message);一个用户对象窥视另一个用户对象时, 所有窥视的文字会传递给用户对象中的这个函数.在此函数中, 您可以处理这些文字.次函数的内容, 通常会再传递给 receive()函数.void telnet_suboption(string buffer); 获得用户终端的一些设置。void write_prompt(void);如果在用户对象中有定义了次函数,则预设的提示符号该显示时, 系统将调用此函数.当用户正处于 input_to(输入文字)和 ed(编辑程序)状态时, 系统不会调用此函数7、、、、所有对象 void create(void);对象的构造函数,对象被系统载入后调用此函数来初始化对象。复制的对象也会调用。需要说明的是,系统第一次载入对象后会自动运行对象和其所有的父类中的create,复制的对象只运行对象自己的create。int id(string an_id);此函数被系统的present()函数调用, 以判断一个指定的对象是否以字符串an_id为识别名称id.如果an_id是此对象的识别名称之一, 就返回 1, 不是则返回 0。void init(void);当系统把对象A放入对象B时(即调用move_object()函数),如果A是人物对象,让A在B里调用A的init函数,同时调用B里面所有对象的init函数。不管A是不是人物对象,让B里所有人物对象调用A的init函数。int move_or_destruct(object dest);如果一个对象的环境对象被摧毁了, 就调用此函数, 并用于它的内容对象.dest是正要被摧毁的对象.如果 dest 不存在, 则 dest 为 0.如果 dest 中的对象没有把自己移出被摧毁的对象, 则也会被一起摧毁.int clean_up(int inherited);系统每过一段时间,对非激活对象调用 clean_up()函数.inherited指出此对象是否有别的对象继承.如果返回 0,此对象将永远不再调用 clean_up().如果返回 1, 则继续判断调用。通常一个对象在 clean_up()中所作的事, 是摧毁自己以节省内存.void reset(void);系统在每次reset之后(时间由系统设定),所有游戏中现存的对象都会调用reset()函数.reset()常用于检查宝物或怪物是否还在某个房间, 以判断要不要重新产生一份.8、、、、一些概念的说明 用户对象用户对象用户对象用户对象((((interactive()):):):):用户连接的对象就是用户对象,系统会调用用户对象的一些方法来实现用户的输入输出和消息处理等。如果用户对象断开连接,用户对象就变成为普通对象。但是系统会记录曾经是用户对象的对象,通过userp()函数可以判断一个对象是否曾经是用户对象。人物人物人物人物对象对象对象对象(living())::::人物对象是曾经呼叫过 enable_commands()的对象,当然用户对象也是人物对象。环境对象环境对象环境对象环境对象(environment())::::环境对象是通过move_object()函数激活的对象。激活激活激活激活对象对象对象对象::::在系统规定的(clear_up)时间内,曾经调用过init()函数的对象。复制复制复制复制对象对象对象对象(clonep())::::系统在第一次载入某个对象后会建立一个初始对象并存于系统内存中,以后每次重新建立对象包括new()、clone_object()、call_other()等都会通过拷贝这个初始对象来建立新的对象,每个拷贝出来的对象,系统都会指定一个递增的数字标识此对象。这里需要说明的是,new()等函数建立对象时,如果初始对象不存在的话,系统会自动载入并初始化此对象,并把此对象定为初始对象,然后再拷贝一个对象作为new()等函数的返回值。系统建立初始对象的时候会由父到子的调用对象所有的create()函数,而拷贝出来的对象只调用对象本身的create()函数。游戏中存在的对象都是复制出来的对象。初始对象只有系统才能调用。 对象对象对象对象uid值值值值::::这个值只能通过主控对象中的creator_file()函数赋值或者export_uid()函数传递。指明当前对象的使用者名称。对象对象对象对象euid值值值值::::对象有效的使用者名称,可以通过seteuid和geteuid函数设置和读取。对象的对象的对象的对象的继承继承继承继承、、、、构造及初始化构造及初始化构造及初始化构造及初始化::::Mudos启动以后,可以自动或者通过函数调用来创建和复制各种对象,Mudos系统的作用就是用来管理这些对象。Mudos在生成对象的时候有两种方式,一种是载入对象,一种是复制已经载入的对象。首先,Mudos是通过对象的文件名来寻找和定位对象的,当需要载入对象的时候,先检查对象是否已经载入,如果没有载入会检查对象是否有需要继承别的对象,如果需要就先载入需要继承的对象,然后再载入并生成需要载入的对象。对象的继承实际上是子对象先浅拷贝一份父对象(但不初始化),然后再构造自己。任何一个对象被载入内存或被复制出来都会执行create函数来初始化自己。9、、、、EFUN函数说明 This_object():这个函数返回由当前文件所建立或拷贝的对象。如果这个文件继承了另一个文件,那么另一个文件中的这个函数也返回由这个文件所建立或拷贝的对象。previous_object(n):返回调用此函数的第前n个对象,previous_object(0)= previous_object(),表示返回调用此函数的对象。This_interactive():返回调用此函数的用户对象。This_player():返回调用此函数的人物对象。This_player(1)返回This_interactive()Load_object():如果已经载入则返回已经载入的对象,否则载入对象并返回它。New():如果对象没载入则载入对象,并复制一个对象返回,否则复制已经载入的对象返回。这里需要指出的是复制对象的过程并不会载入被复制对象所要继承的对象。Clone_object():和new一样,目前不知道有什么区别。replace_program():这个函数是用当前对象的继承对象来替换当前对象,但是保留当前对象的全局变量。就是说如果被替换以后,当前对象就只有继承对象的方法,而当前对象所定义的方法都不存在了。第五篇:Mudos编程总结[推荐]