通讯录编程一、所在实现的功能:(1) 可通过文件导入和导出通信录信息(2) 可向前或向后浏览通信录(3)可添加、修改和删除通信记录如下图所示,点击添加数据(点击后会变为浏览记录)开始进行添加数据,输入完数据后点击保存,数据才能被保存,添加完数据后,可以再点浏览记录,对添加完的数据进行浏览,在保存有记录和浏览记录时,可以对记录进行修改和删除。
图1-1单击打开文件可以打开以前保存的记录,单击保存文件可以将当前保存的记录保存进一个text格式的文件中。
二、设计思路:首先新建一个CPerson的类,在其中添加成员变量以保存所需要保存的信息,然后使其派生于Cobject类,并将其串行化,用一个CPerson的对象来保一个人的个人信息,并在MFC生成的CMyDlg类中定义一个CObList的对象m_PersonViewList来保存所生成的CPerson对象。
并用CArchive来对m_PersonViewList的元素进行保存和读取。
三、设计过程:1、CPerson建立:点击菜单栏中的Insert,插入一个新类,名使其从CObject 派生出来,并将其串行化,其代码如下:(1) 头文件代码:class CPerson:public CObject//将其从CObject类中派生出来{public:DECLARE_SERIAL(CPerson) //对类进行串行化宏定义CPerson(); //添加无参数的构造函数,用于从文件中读取时来构造此函数CPerson(CString m_Name,CString m_Phone,CString m_Company,CString m_Email);//构造带参数的构造函数用于传递需要保存的数据virtual ~CPerson();CString m_Name; //姓名CString m_Phone; //电话CString m_Company; //公司CString m_Email; //Emailpublic:virtual void Serialize(CArchive& ar); //定义一个Serialize虚函数};(2) 源文件:IMPLEMENT_SERIAL(CPerson,CObject,0)/使用IMPLEMENT_SERIAL宏CPerson::CPerson(){}CPerson::CPerson(Cstring m_Name,Cstring m_Phone,CStringm_Company,CString m_Email){//初始化人员信息(m_Name,m_Phone,m_Company,m_Email)this->m_Name=m_Name; //姓名this->m_Phone=m_Phone; //电话this->m_Company=m_Company; //公司this->m_Email=m_Email; //Email}CPerson::~CPerson(){}void CPerson::Serialize(CArchive& ar)//重定Serialize函数{if (ar.IsStoring())//判断是否是存储状态{ar<<m_Name<<m_Phone<<m_Company<<m_Email;//存储所需要存储的数数// storing code}else//如果是读取数据{ // loading codear>>m_Name>>m_Phone>>m_Company>>m_Email;//读取数据}}(3)小结:将一个类对象串行化需要五个步骤:<1> 从CObject 派生类(或从CObject 派生的某个类中派生);<2> 重写Serialize 成员函数。
<3> 使用DECLARE_SERIAL 宏(在类声明中)。
<4> 定义不带参数的构造函数。
<5> 为类在实现文件中使用IMPLEMENT_SERIAL 宏。
2、界面各控件功能的实现:程序界面设计如图1-1所示,下面将分别对各控件所实现的功能及代码分别进行简单介绍:(1)EditBox控件:用户可以通过界面的四个EditBox输入每个人的个人信息,如姓名、电话、单位、Email。
用ClassWizard生成向导,使每个EditBox控件分别与CmyDlg中的四个成员变量m_Name、m_Phone、m_Company、m_Email关联起来,即使用户输入EditBox的记录分别保存于这四个变量,其代相关代码如下:enum { IDD = IDD_MY_DIALOG };CString m_Name;CString m_Phone;CString m_Company;CString m_Email;void CMyDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CMyDlg)DDX_Text(pDX, IDC_EDIT1, m_Name);DDX_Text(pDX, IDC_EDIT2, m_Phone);DDX_Text(pDX, IDC_EDIT3, m_Company);DDX_Text(pDX, IDC_EDIT4, m_Email);//}}AFX_DATA_MAP}由于四个成员变量都在DoDataExchange中与四个EditBox关联起来了,所以每次刷新记录时都需要调用UpdateData()函数。
(2)添加记录按钮:当程序开始运行时,点击此按钮可以进行添加记录,此时,该按钮的Caption由“添加记录变”为“浏览记录”,并使按钮“保存”可操作,此时可输入记录并保存。
再次点击此按钮,可使按钮“向前浏览”、“向后浏览”、“删除记录”、“修改记录”可操作,并可以浏览此前所添加的数据并对其进行删除和修改记录。
其关联的代码如下所示:void CMyDlg::OnButtonChange(){((CDialog*)this)->GotoDlgCtrl(GetDlgItem(IDC_EDIT1));CString str;GetDlgItem(IDC_BUTTON_CHANGE)->GetWindowText(str);if(str=="添加记录"){((CButton*)GetDlgItem(IDC_BUTTON_PREVIOUS))->EnableWindow(false) ;((CButton*)GetDlgItem(IDC_BUTTON_NEXT))->EnableWindow(false);((CButton*)GetDlgItem(IDC_BUTTON_DELET))->EnableWindow(false);((CButton*)GetDlgItem(IDC_BUTTON_MODIFY))->EnableWindow(false);((CButton*)GetDlgItem(IDC_BUTTON_ADD))->EnableWindow(TRUE);((CBu tton*)GetDlgItem(IDC_BUTTON_CHANGE))->SetWindowText("浏览通讯录");//清空编辑窗口m_Name="";m_Phone="";m_Company="";m_Email="";UpdateData(false);//刷新窗口}else{((CButton*)GetDlgItem(IDC_BUTTON_ADD))->EnableWindow(FALSE);((CButton*)GetDlgItem(IDC_BUTTON_DELET))->EnableWindow(TRUE);((CButton*)GetDlgItem(IDC_BUTTON_MODIFY))->EnableWindow(TRUE)((C Button*)GetDlgItem(IDC_BUTTON_PREVIOUS))->EnableWindow(TRUE);((CButton*)GetDlgItem(IDC_BUTTON_NEXT))->EnableWindow(TRUE); ((CButton*)GetDlgItem(IDC_BUTTON_CHANGE))->SetWindowText("添加记录");if(!m_PersonViewList.IsEmpty ()){CPerson *pListDoc=(CPerson*)m_PersonViewList.GetAt(m_Position);//获得前一个人员的信息m_Name=pListDoc->m_Name;m_Phone=pListDoc->m_Phone;m_Company=pListDoc->m_Company;m_Email=pListDoc->m_Email; //赋值给视图类数据成员UpdateData(false);//刷新窗口}}}(3)保存按钮:此按钮提供保存添加记录的功能,当向四个EditBox框中输入数据后,可点击此按钮对信息进行保存,如果EditBox中没有输入作任何数据,则弹出MessageBox对话框,要求先输入数据,其实现代码如下:void CMyDlg::OnButtonAdd(){// TODO: Add your control notification handler code hereUpdateData(true);if(m_Company==""&&m_Name==""&&m_Phone==""&&m_Email=="")//判断是否输入数据;{MessageBox("请先输入数据");}else{((CDialog*)this)->GotoDlgCtrl(GetDlgItem(IDC_EDIT1));UpdateData(TRUE);CPerson *pListDoc=new CPerson(m_Name,m_Phone,m_Company,m_Email);//定义一个指向CPerson的对象的指针,用于保存其信息m_Position=m_PersonViewList.AddTail(pListDoc);//将新生成的对象保存于m_PersonViewList对像链表的尾部,并用m_Position来保存其在m_PersonViewList对像链表的位置m_Name="";m_Phone="";m_Company="";m_Email="";UpdateData(false);//刷新记录}}(4)向前浏览按钮:用于向前浏览所保存的记录,其实现代码如下:void CMyDlg::OnButtonPrevious(){// TODO: Add your control notification handler code here if(m_PersonViewList.IsEmpty ())//判断对象链表是否为空{MessageBox("请先添加记录");}else{POSITION m_templeposition;//定义一个临时位置指针m_templeposition=m_Position;//并使其指向当前结点的前驱结点m_PersonViewList.GetPrev(m_templeposition);//获得当前结点位置的前一个if(m_templeposition==NULL){AfxMessageBox(_T("已到表头!"));}else{m_Position=m_templeposition;//当前指针定位到前一个CPerson *pListDoc=(CPerson *)m_PersonViewList.GetAt(m_Position);//获得前一个人员的信息m_Name=pListDoc->m_Name;m_Phone=pListDoc->m_Phone;m_Company=pListDoc->m_Company;m_Email=pListDoc->m_Email; //赋值给视图类数据成员UpdateData(false);//刷新窗口}}}(5)向后浏览按:单击此按钮,可向后浏览所保存的记录,若没有记录得有数据,刚提示先输入数据,当到达链表尾,则提示已到达列表尾,其实现代码如下:void CMyDlg::OnButtonNext(){// TODO: Add your control notification handler code hereif(m_PersonViewList.IsEmpty ()){MessageBox("请先添加记录");}else{POSITION m_templeposition;//定义一个临时位置指针m_templeposition=m_Position;//并使其指向当前结点的前驱结点m_PersonViewList.GetNext(m_templeposition);//获得当前结点位置的后一个if(m_templeposition==NULL){AfxMessageBox(_T("已到表尾!"));}else{m_Position=m_templeposition;//当前指针定位到后一个CPerson *pListDoc=(CPerson *)m_PersonViewList.GetAt(m_Position);//获得前一个人员的信息m_Name=pListDoc->m_Name;m_Phone=pListDoc->m_Phone;m_Company=pListDoc->m_Company;m_Email=pListDoc->m_Email; //赋值给视图类数据成员UpdateData(false);//刷新窗口}}}(6)删除记录:在浏览过程中,可对保存的记录进行删除,并在窗口中显示下一个人物的信息,若下一个人的信息不存在,则显示上一个人的信息,其实现代码如下:void CMyDlg::OnButtonDelet(){if(m_PersonViewList.IsEmpty ())//判断m_PersonViewList是否为空{MessageBox("请先添加记录");}else{POSITION temposition;temposition=m_Position;m_PersonViewList.GetNext (temposition);if(temposition==NULL){POSITION tempos;tempos=m_Position;m_PersonViewList.GetPrev (tempos);CPerson *pListDoc=(CPerson *)m_PersonViewList.GetAt(tempos);//获得前一个人员的信息m_Name=pListDoc->m_Name;m_Phone=pListDoc->m_Phone;m_Company=pListDoc->m_Company;m_Email=pListDoc->m_Email; //赋值给视图类数据成员UpdateData(false);//刷新窗口CObject *pOld; //临时对象指针pOld=m_PersonViewList.GetAt(m_Position);//使其指向当前指针m_PersonViewList.RemoveAt(m_Position); //将当前结点从列表中删除delete pOld;//释放空间m_Position=m_PersonViewList.GetTailPosition ();//将CobList中的最后个元素的地址传给m_Position;}else{CPerson *pListDoc=(CPerson*)m_PersonViewList.GetAt(temposition);//获得后一个人员的信息m_Name=pListDoc->m_Name;m_Phone=pListDoc->m_Phone;m_Company=pListDoc->m_Company;m_Email=pListDoc->m_Email; //赋值给视图类数据成员UpdateData(false);//刷新窗口CObject *pOld; //临时对象指针pOld=m_PersonViewList.GetAt(m_Position);//使其指向当前指针m_PersonViewList.RemoveAt(m_Position); //将当前结点从列表中删除delete pOld;//释放空间m_Position=temposition;}}}(7)修改数据:当在浏览过程中时,可通过点击此按钮来修改当前所保存的记录。