对话框是一种用于用户交互的窗口类型,通常包含各种控件,如按钮、文本框等,用户可以通过这些控件与程序交互。在MFC中,可以使用对话框类来创建和管理对话框。
要基于对话框进行编程,首先需要创建一个对话框资源,并将其添加到您的MFC项目中。然后,您需要创建一个对话框类,该类继承自CDialog或其派生类。在对话框类中,您可以处理对话框消息和控件事件,并执行所需的操作。
例如,您可以在对话框类中添加一个按钮,并为该按钮添加一个单击事件处理程序。在事件处理程序中,您可以编写代码以响应按钮单击事件,例如弹出一个消息框或执行一些其他操作。以下是一个简单的示例:
- 创建一个对话框资源。
- 创建一个对话框类,例如MyDialog,该类继承自CDialog类。
- 在对话框类头文件中添加一个成员函数,例如OnButtonClick。
- 在对话框类CPP文件中实现OnButtonClick函数,例如弹出一个消息框。
- 在对话框类中添加一个按钮控件,并将其与OnButtonClick事件处理程序关联。
这样,当用户单击该按钮时,系统将调用对话框类中的OnButtonClick函数,从而执行您所编写的代码。
C++MFC是Microsoft Foundation Classes的缩写,是一种用于Windows操作系统的C++应用程序框架。它提供了一组类和函数,使得开发者可以使用面向对象的方法创建Windows GUI应用程序。
MFC主要包含以下几个部分:
- 应用程序类(CWinApp):处理应用程序的初始化、消息循环等操作。
- 窗口类(CWnd):封装了Windows窗口的基本行为,如位置、大小、可见性等。
- 对话框类(CDialog):用于创建对话框界面。
- 控件类:如按钮、文本框、列表框等,用于与用户交互。
- 消息映射机制:将Windows消息与类成员函数关联起来,实现事件响应功能。
MFC在Windows桌面应用程序开发中得到广泛应用,特别是当需要调用Win32 API时,MFC的封装能够简化代码,提高开发效率。但随着移动端和Web应用的兴起,MFC的应用范围逐渐收缩。
利用MFC写一个通讯录系统
学习资源推荐
基于MFC的简易通讯录:
https://blog.csdn.net/weixin_43978807/article/details/90725232?spm=1001.2014.3001.5506
面向对象程序设计课程设计——MFC实现同学通讯录管理系统:
https://blog.csdn.net/weixin_44244154/article/details/103733614?spm=1001.2014.3001.5506
1.设计目的
同学通讯录管理程序是为了更好地管理学生信息而开发的数据管理软件。如今,同学与同学、老师与同学联系都是通过电话联系。但是,通常这些数据与其他人的信息混合在一起,同学信息并不方便被整理。
所以,同学通讯录管理程序为用户提供充足的信息和快捷的查询手段,实现学生基本信息的录入,删除,查询,修改,存到文件等几方面的功能,这样能对同学之间的信息进行更好的管理,使老师能更好地管理学生信息,对学生信息出现的变动也能及时进行修改。
与此同时,对所学面向对象的程序设计中所学知识加以利用和巩固:
1) 学习Visual C++的MFC开发程序的步骤。
2) 综合运用所学的类、继承和多态的知识。
3) 进一步掌握程序的调试方法。
- 设计内容
1 利用MFC的向导,创建基于对话框的应用程序,添加按钮、编辑框等控件;
2 设计通讯录的数据结构(如:以数组或者动态链表)和相应的类;
3 完成对通讯录中记录的增加、修改、删除和显示。
4 将通讯录存入文件。能够打开并显示其中所存的同学信息,并可以进行后续的操作。
在设计同学通讯录管理程序时,我们小组采用对话框形式来进行处理,因为对话框窗口操作简单,更重要的是能更好的向使用者表达程序所要表达的信息。
在主界面进行设计时,我们小组分别设计了学号,姓名,系别,邮箱,电话等五个输入输出框,分别对学生的信息进行输入与输出。其次,设计了一个列表框使学生信息能更好的向用户展示,同时也更加方便了以后的操作。
最后,分别设计了添加记录、查询记录、删除记录、修改记录、保存信息、读取信息、清空所有数据和退出八个按钮,分别实现各自所对应的功能。
3.基本功能描述
3.1. 编辑框
**学号,姓名,系别,邮箱,电话静态文本后的输入输出框实现了对学生信息数据的输入输出。
3.2. 列表框
实现了对学生各个信息的显示,同时通过点击列表中的某一项来实现查看、修改等功能。
3.3. 按钮
- 添加记录:用户在输入输出框中输入信息,然后通过点击添加记录按钮,添加到列表框中。
- 查询记录:在除了系别这一信息外任意输入某一项或某几项信息后,点击查询记录按钮,程序将以姓名、电话、邮箱、学号的优先级递减顺序来查找符合条件的学生并将查询到的学生信息显示在输入输出框中。
- 删除记录:通过选中列表框中某一项,点击删除记录按钮删除所对应的学生数据,但不影响文件中的数据。
- 修改记录:通过选中列表框中某一项,在对话框中修改所对应的学生某项数据,然后点击修改记录按钮,修改列表框中所对应的数据信息,但不影响文件中的数据。
- 保存信息:将列表框中的信息全部保存到,目录下的“学生信息.txt”文件中,只有生成文件按钮才会通过程序影响文件中的内容。
- 读取信息:首先将列表中的已经显示的信息全部清空,再将储存在文件中的信息读取中列表中。
- 清空所有数据:删除全部学生信息,清空所有记录,同时也将文件中的信息清空。
- 退出:点击退出后弹出消息框“是否确认退出?”,若点击确认则退出程序,点击取消则返回当前程序**
4.设计思路
4.1. 窗口的设计
新建对话框程序,在对话框程序中添加各个控件,实现各个功能。
首先创建一般Student类,其中有共有CString公有数据成员name,number,phone,email,yuanxi,分别实现对学生邮箱,姓名,学号,电话,系别的存储。
class Student{ public: CString name; CString number; CString phone; CString email; CString yuanxi; };
再声明自定义类型Student的向量stu(初始容量为零)和用以确定列表控件行数的全局变量n(初始值为-1)。
为对话框创建CClassAddresslistDlg类,并设置各个变量与对话框各个窗口相关联。
通过编写点击各个按钮对应函数来完成各个按钮的功能:
添加记录:void CClassAddresslistDlg::OnBUTTONincrease();
查询记录:void CClassAddresslistDlg::OnBUTTONSearch();
删除记录:void CClassAddresslistDlg::OnBUTTONdelete();
修改记录:void CClassAddresslistDlg::OnBUTTONchange();
保存信息:void CClassAddresslistDlg::OnBUTTONpreserve();
读取信息:void CClassAddresslistDlg::OnBUTTONduqu();
清空所有数据:void CClassAddresslistDlg::OnBUTTONqingkong();
退出:void CClassAddresslistDlg::OnButtontuichu();
5.软件设计
5.1. 设计步骤
- 打开VC++6.0,新建MFC AppWizard[EXE]工程,在对话框中添加各个控件,完成程序窗口外观设计
- 在MFC ClassWizard中建立对话框类,并命名为CClassAddresslistDlg
- 在MFC ClassWizard中建立一般类,并命名为Student
- 在CStudentDlg类编写时,创建全局变量int n = -1(代表行数),通过n的值来方便为列表和按钮建立联系
- 在MFC ClassWizard为CStudentDlg中添加各个控件,并通过函数编写,实现具体的功能
- 调试与运行
5.2界面设计
界面由选项框区、通讯录信息区以及列表控件区三个区域组成。其中,通讯录信息区由有五个静态控件用来显示“学号”“姓名”“系别”“邮箱”“电话”字样,与各个静态控件相对应的是五个编辑框,实现了对学生信息的输入输出。列表框区用来显示当前已经存储的学生信息,选项框区有八个按钮,分别对应各自的功能。
6.关键功能的实现
*添加纪录:
首先用户需要在五个编辑框中分别输入信息。点击“添加纪录”按钮后,对应的函数首先声明将编辑框控件中的内容同步到变量中,接着声明了一个变量int flag = 1,用来选择性地执行接下来的if语句。接下来判断当前状态下用户是否输入了信息以及用户输入的信息是否已经在列表中,如果输入了合理的信息则执行接下来的if语句进行查找,反之则改变flag的值以避开用于加入新元素的if语句。随后将信息栏当中的关联变量置零,进行下一次操作时信息栏当中不再显示上次学生的信息。
保存信息:
将保存信息按钮与Dlg类相关联,用户点击保存信息后,利用IO流对数据进行输入和输入,采用ofstream新建一个对象out来打开一个文本文档,采取ios::trunc对文本文件中已有数据进行覆盖,并将变量中的信息利用out来储存到文本文件当中去,每输入一个学生的信息进行换行操作。由于CString是MFC中,而ofstream是ATL中,ofstream能写入的需要char ,因此需要进行类型的转化,来实现信息的保存。
读取信息:
将读取信息按钮与Dlg类相关联,用户点击读取信息后利用IO流对数据进行输入和输入,采用ifstream新建一个对象fin来打开一个文本文档,先利用list控件中的函数将列表清空,
同样需要进行类型的转化,再利用fin将文档中的内容输出到列表中,并与变量的数据相关联,将其同步到变量当中去,来实现信息的读取。
列表控件:
单击列表中的某一行,再左侧信息栏中对应出现相应的学生信息。将列表栏与Dlg类相关联,获得相应的学生信息后将其同步到信息栏的关联变量当中,实现列表栏与信息栏的同步。
7.核心代码实现
7.1列表控件与编辑框控件的关联:
void CClassAddresslistDlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult) //使选中哪一行的信息编辑框出现哪一行的信息 { POSITION pos=m_list.GetFirstSelectedItemPosition(); //获得选中元素的位置 n=m_list.GetNextSelectedItem(pos); //获得选中元素的索引 CString x; x=m_list.GetItemText(n,0); m_Number=x; x=m_list.GetItemText(n,1); m_Name=x; x=m_list.GetItemText(n,2); m_Xibie=x; x=m_list.GetItemText(n,3); m_Email=x; x=m_list.GetItemText(n,4); m_Phone=x; UpdateData(false); *pResult = 0; }
7.2 添加纪录:
void CClassAddresslistDlg::OnBUTTONincrease() { int flag = 0;//以便于选择性执行if语句 UpdateData(true); if(m_Name==""||m_Number==""||m_Xibie==""|| m_Phone==""||m_Email=="") { flag = 1; MessageBox("输入信息不完善,请重新输入!"); } if (flag==0) for (int i = 0;i < stu.size();i++) { if ( stu[i].name == m_Name&&stu[i].phone == m_Phone&&stu[i].email == m_Email&&stu[i].number == m_Number&&stu[i].yuanxi == m_Xibie) { flag = 1; MessageBox("该学生信息已经添加!"); break; } } if (flag==0) { int n=m_list.GetItemCount(); m_list.InsertItem(n,""); m_list.SetItemText(n,0,m_Number); m_list.SetItemText(n,1,m_Name); m_list.SetItemText(n,2,m_Xibie); m_list.SetItemText(n,3,m_Email); m_list.SetItemText(n,4,m_Phone); stu.reserve(stu.size()+1);//增加容量以防止溢出 Student s1; s1.name = m_Name; s1.number = m_Number; s1.yuanxi = m_Xibie; s1.email = m_Email; s1.phone = m_Phone; stu.push_back(s1);//往向量末尾加新信息 MessageBox("添加成功!"); m_Name=""; m_Number=""; m_Xibie=""; m_Phone=""; m_Email=""; //清空编辑框 UpdateData(false); } }
7.3 保存信息:
void CClassAddresslistDlg::OnBUTTONpreserve() { ofstream fout("ZHM.txt",ios::trunc); int n=m_list.GetItemCount(); for(int i=0;i<n;++i){ string str = CString(stu[i].number); //由于CString是MFC中,而ofstream是ATL中,ofstream能写入的需要char * string str1 = CString(stu[i].name); string str2 = CString(stu[i].yuanxi); string str3 = CString(stu[i].email); string str4 = CString(stu[i].phone); fout<<str.c_str()<<" " <<str1.c_str()<<" " <<str2.c_str()<<" " <<str3.c_str()<<" " <<str4.c_str()<<endl; if (fout.fail()) break; } fout.close(); MessageBox("保存成功!"); }
7.4 读取信息:
void CClassAddresslistDlg::OnBUTTONduqu() { m_list.DeleteAllItems(); // 全部清空 ifstream fin("ZHM.txt",ios_base::in); string a,b,c,d,e; fin>>a>>b>>c>>d>>e; for(int i=0;!fin.fail();++i){ int n=m_list.GetItemCount(); m_list.InsertItem(n,a.data()); m_list.SetItemText(n,1,b.data()); m_list.SetItemText(n,2,c.data()); m_list.SetItemText(n,3,d.data()); m_list.SetItemText(n,4,e.data()); MessageBox("读取成功!"); Student s1; s1.number=a.data(); s1.name=b.data(); s1.yuanxi=c.data(); s1.email=d.data(); s1.phone=e.data(); stu.reserve(stu.size()+1);//增加容量以防止溢出 stu.push_back(s1); fin>>a>>b>>c>>d>>e; } fin.close(); }
其他
用C++的MFC编写一个通讯录系统,可以采用对话框为主界面,配合列表控件(CListCtrl)显示联系人信息。以下是一个简单的思路和基本的代码实现:
- 创建MFC项目,并选择基于对话框的应用程序。
- 在对话框中放置一个列表控件(ID为IDC_LIST_CONTACTS),并设置其属性以显示网格线和全行选中。在对话框类中添加成员变量
CListCtrl m_listContacts;
与该控件关联。 - 为了方便管理,我们可以创建一个Contact结构体,包含姓名、电话等成员。
- 在初始化对话框时,添加列表控件的列标题。
- 添加功能按钮,如添加、删除、修改联系人。
以下是一个简单代码示例:
// ContactManagerDlg.h #pragma once #include "afxcmn.h" struct Contact { CString name; CString phone; }; class CContactManagerDlg : public CDialogEx { public: CContactManagerDlg(CWnd* pParent = NULL); enum { IDD = IDD_CONTACTMANAGER_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); protected: HICON m_hIcon; virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: CListCtrl m_listContacts; std::vector<Contact> m_contacts; afx_msg void OnBnClickedButtonAdd(); afx_msg void OnBnClickedButtonDelete(); afx_msg void OnBnClickedButtonEdit(); };
// ContactManagerDlg.cpp #include "stdafx.h" #include "ContactManager.h" #include "ContactManagerDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif CContactManagerDlg::CContactManagerDlg(CWnd* pParent /*=NULL*/) : CDialogEx(IDD_CONTACTMANAGER_DIALOG, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CContactManagerDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST_CONTACTS, m_listContacts); } BEGIN_MESSAGE_MAP(CContactManagerDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_ADD, &CContactManagerDlg::OnBnClickedButtonAdd) ON_BN_CLICKED(IDC_BUTTON_DELETE, &CContactManagerDlg::OnBnClickedButtonDelete) ON_BN_CLICKED(IDC_BUTTON_EDIT, &CContactManagerDlg::OnBnClickedButtonEdit) END_MESSAGE_MAP() BOOL CContactManagerDlg::OnInitDialog() { CDialogEx::OnInitDialog(); SetIcon(m_hIcon, TRUE); SetIcon(m_hIcon, FALSE); m_listContacts.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 100); m_listContacts.InsertColumn(1, _T("Phone"), LVCFMT_LEFT, 100); return TRUE; } void CContactManagerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } HCURSOR CContactManagerDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CContactManagerDlg::OnBnClickedButtonAdd() { // 实现添加联系人功能 } void CContactManagerDlg::OnBnClickedButtonDelete() { // 实现删除选中联系人功能 } void CContactManagerDlg::OnBnClickedButtonEdit() { // 实现编辑选中联系人功能 }
上述代码实现了一个基本的通讯录界面和对应的数据结构。需要注意这里并未实现具体的添加、删除和编辑功能,你可以根据需要进一步完善。此外,为了持久化通讯录数据,还可以考虑将联系人信息保存到文件或数据库中,并在启动时加载。
接下来,我们将实现添加、删除和编辑联系人的功能。首先需要创建一个新的对话框用于输入联系人信息(如姓名和电话),可以命名为CContactDlg
。
在CContactDlg
中,添加两个编辑框控件分别用于输入姓名和电话,为它们分别添加成员变量m_strName
和m_strPhone
。
然后,在CContactManagerDlg
类中实现添加、删除和编辑功能:
void CContactManagerDlg::OnBnClickedButtonAdd() { CContactDlg dlg; if (dlg.DoModal() == IDOK) { Contact newContact; newContact.name = dlg.m_strName; newContact.phone = dlg.m_strPhone; m_contacts.push_back(newContact); int nIndex = m_listContacts.GetItemCount(); m_listContacts.InsertItem(nIndex, newContact.name); m_listContacts.SetItemText(nIndex, 1, newContact.phone); } } void CContactManagerDlg::OnBnClickedButtonDelete() { POSITION pos = m_listContacts.GetFirstSelectedItemPosition(); if (pos) { int nSelected = m_listContacts.GetNextSelectedItem(pos); m_listContacts.DeleteItem(nSelected); m_contacts.erase(m_contacts.begin() + nSelected); } } void CContactManagerDlg::OnBnClickedButtonEdit() { POSITION pos = m_listContacts.GetFirstSelectedItemPosition(); if (pos) { int nSelected = m_listContacts.GetNextSelectedItem(pos); CContactDlg dlg; dlg.m_strName = m_contacts[nSelected].name; dlg.m_strPhone = m_contacts[nSelected].phone; if (dlg.DoModal() == IDOK) { m_contacts[nSelected].name = dlg.m_strName; m_contacts[nSelected].phone = dlg.m_strPhone; m_listContacts.SetItemText(nSelected, 0, dlg.m_strName); m_listContacts.SetItemText(nSelected, 1, dlg.m_strPhone); } } }
现在,你已经实现了一个基本的通讯录系统。接下来可以考虑优化和新增功能,例如:
- 将联系人信息保存到文件或数据库中,并在启动时加载。
- 添加搜索功能,允许用户搜索联系人。
- 支持按姓名、电话等字段排序联系人列表。
- 改进UI,使其更美观易用。
根据自己的需求和兴趣,你可以不断完善这个通讯录系统,使其更加强大和实用。
博客园
一、功能 构思确定通讯录的功能 1. 基本功能 - 添加联系人 - 删除联系人 - 修改联系人 - 显示联系人信息 2. 附加功能 - 查找联系人 - 读取保存联系人信息 3. 创意小功能 - 显示备注 - 电话号码必须为11位 - 双击报表视图中联系人即可修改联系人信息 - 查找联系人时报表视图只显示匹配的联系人信息 - 不允许添加重复联系人信息(一名联系人可以有多个电话) - 未选中报表视图中联系人时修改联系人和删除联系人按钮不可用 - 查找联系人时根据关键字进行查找(即输入名字或电话的一部分或者仅选择群组都可以查找到匹配的联系人) 二、设计布局 1. 主对话框布局 在这里插入图片描述 左上角为List Control控件 所有虚线框都为Group Box控件 备注框为List Box控件 查找联系人中姓名框和电话框为Edit Control控件 查找联系人中群组框为Combo Box控件 查找联系人中姓名、电话和群组为Static Text控件 其余为Button控件 2. 添加联系人和修改联系人子对话框布局(两个对话框) 在这里插入图片描述 控件与主对话框的控件类型一样(自己判断) 通过点击主对话框中的添加联系人和修改联系人按钮分别弹出子对话框。 新建MFC应用程序的过程省略,类型选择基于对话框。(基本操作默认都会,不会的请自行百度) 子对话框可将自带的确认和取消按钮的Caption属性改成保存和取消即可。 在资源视图中的Dialog插入两个新的对话框作为上述两个子对话框。 三、设置类、成员变量、命令、及虚函数 通过类向导进行此步操作 1. 类 分别为三个对话框添加类,命名随意即可。MailListtDlg ContactAdding ContactModifying分别为本通讯录的主对话框类、添加联系人子对话框类、修改联系人子对话框类。(右键点击对话框找到添加类) 2. 成员变量 命名随意即可。 主对话框的成员变量 在这里插入图片描述第1、2项分别为群组框Combo Box的控件类别变量和值类别变量,第3、4、5、6项分别为姓名框和电话框Edit Control的控件类别变量和值类别变量,第7项为备注框List Box的控件类别变量,第8项为报表视图List Control的控件类别变量。 子对话框的成员变量 在这里插入图片描述 第1、2项为群组框Combo Box的控件类别变量和值类别变量,第3、4、5项分别为姓名框、电话框、备注框Edit Control的值类别变量。 3. 命令 主对话框的命令 所有Button控件添加单击响应函数BN_CLICKED,List Control控件添加消息NM_CLICK DBLCLK。 子对话框的命令 所有Button控件添加单击响应函数BN_CLICKED。(若是将对话框自带的确认和取消按钮的Caption属性改成保存和取消则不用进行此项操作) 4. 虚函数 只需为两个子对话框各自添加一个初始化函数OnInitDialog。 四、代码编写 以下代码的类名请根据自己之前的命名进行修改,对象名的命名随意。不懂的函数自行百度(我都是百度看懂的)。代码的顺序按功能的构思思路进行安排。 1. 添加一个类存储联系人各项信息 新建一个头文件将此类写进去,在需要用到此类的cpp文件中include此头文件。 class MyClass { public: //姓名,5个字内 char Name[12]; //电话,11个数字 char Phone[13]; //群组 char Group[10]; //群组索引(因为群组是ComboxBox控件,所以需要索引) //初始化-1是为了当通讯录没有数据进行保存时不会错误将数据写入文件) int Group_Index = -1; //备注,50个字以内 char Remark[104]; }; 2、添加全局变量统计联系人人数和存储各个联系人 stdafx.h //统计联系人人数 extern int N; //存储各个联系人 extern MyClass new_people[100]; ----------------------------------------------------------------------- stdafx.cpp int N = 0; MyClass new_people[100]; 3、主对话框的初始化函数 实现读取保存联系人信息功能。在头文件中进行read函数的声明,在实现文件中进行read函数的定义;read函数用于读入文件中已有的联系人信息,初始化函数用读入的联系人信息进行初始化主对话框,在报表视图中显示联系人信息。 read函数 MailListtDlg.h void read(); ----------------------------------------------------------------------- MailListtDlg.cpp void CMailListtDlg::Read(){ CStdioFile file; CString str; file.Open("test.txt", CFile::modeRead); int now = 0; while (file.ReadString(str) != NULL){ int i; if (now == 0) { N++; for (i = 0; i < str.GetLength(); i++) { new_people[N - 1].Name[i] = str[i]; } new_people[N-1].Name[str.GetLength()] = '\0'; } else if (now == 1) { for (i = 0; i < str.GetLength(); i++) { new_people[N-1].Phone[i] = str[i]; } new_people[N-1].Phone[str.GetLength()] = '\0'; } else if (now == 2) { strcpy_s(new_people[N-1].Group, str); } else if (now == 3) { new_people[N - 1].Group_Index = _ttoi(str); } else if (now == 4) { for (i = 0; i < str.GetLength(); i++) { new_people[N - 1].Remark[i] = str[i]; } new_people[N-1].Remark[str.GetLength()] = '\0'; } now++; now %= 5; } } 初始化函数 BOOL CMailListtDlg::OnInitDialog(){ CDialogEx::OnInitDialog(); //初始化时读取文件内容,自定义的Read函数读取文件 CMailListtDlg Read; Read.Read(); SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 //设置报表视图的头标题 CRect rect; CListCtrl* pmyListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST4); LONG dwStyle = GetWindowLong(pmyListCtrl->m_hWnd, GWL_STYLE); SetWindowLong(pmyListCtrl->m_hWnd, GWL_STYLE, dwStyle | LVS_REPORT); LONG styles = pmyListCtrl->GetExtendedStyle(); pmyListCtrl->SetExtendedStyle(styles | LVS_EX_FULLROWSELECT |LVS_EX_GRIDLINES | LVS_NOSCROLL); pmyListCtrl->GetWindowRect(&rect); pmyListCtrl->InsertColumn(0, "姓名", LVCFMT_CENTER, rect.Width() / 3); pmyListCtrl->InsertColumn(1, "电话", LVCFMT_CENTER, rect.Width() / 3); pmyListCtrl->InsertColumn(2, "群组", LVCFMT_CENTER, rect.Width() / 3); //当导入了联系人信息且联系人信息非空时,报表视图按文本中联系人信息顺序显示 int nlist = m_ListCtrl.GetItemCount(); if (new_people[0].Group_Index != -1) { CString str; for (int i = N - 1; i >= 0; i--) { str.Format("%s", new_people[i].Name); m_ListCtrl.InsertItem(nlist, str); str.Format("%s", new_people[i].Phone); m_ListCtrl.SetItemText(nlist, 1, str); str.Format("%s", new_people[i].Group); m_ListCtrl.SetItemText(nlist, 2, str); } } //Combo Box控件显示内容 m_zhuGroup.AddString(_T("")); m_zhuGroup.AddString(_T("无")); m_zhuGroup.AddString(_T("家人")); m_zhuGroup.AddString(_T("朋友")); m_zhuGroup.AddString(_T("同学")); m_zhuGroup.SetCurSel(0); //修改和删除联系人按钮灰显 GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE); return TRUE; } 4. 单击“添加联系人”按钮的响应函数 void CMailListtDlg::OnBnClickedButton1() { ContactAdding dlg; //弹出添加联系人子对话框,当子对话框通过保存键关闭时,进行if内的操作 if (IDOK == dlg.DoModal()) { //添加联系人到报表视图 并存储到全局变量 //获取当前报表视图的行数 int i; CString str; int nHeadNum = m_ListCtrl.GetItemCount(); //姓名 str = dlg.m_Name2; str.TrimLeft(); str.TrimRight(); //报表视图中插入姓名 m_ListCtrl.InsertItem(nHeadNum, str); //将姓名存储到全局变量 for (i = 0; i < str.GetLength(); i++){ new_people[N].Name[i] = str[i]; } new_people[N].Name[str.GetLength()] = '\0'; //电话 str = dlg.m_Phone2; //报表视图中插入电话 m_ListCtrl.SetItemText(nHeadNum, 1, str); //将电话存储到全局变量 for (i = 0; i < 11; i++){ new_people[N].Phone[i] = str[i]; } new_people[N].Phone[11] = '\0'; //将群组索引存储到全局变量 new_people[N].Group_Index = dlg.Group_Index; //将群组存储到全局变量 m_zhuGroup.GetLBText(new_people[N].Group_Index + 1, new_people[N].Group); //报表视图插入群组 m_ListCtrl.SetItemText(nHeadNum, 2, new_people[N].Group); //备注 str = dlg.m_Variable2; str.TrimLeft(); str.TrimRight(); //将备注存储到全局变量 for (i = 0; i < str.GetLength(); i++){ new_people[N].Remark[i] = str[i]; } new_people[N].Remark[str.GetLength()] = '\0'; //联系人人数+1 N++; } } 进入添加联系人子对话框的初始化函数 BOOL ContactAdding::OnInitDialog() { CDialogEx::OnInitDialog(); //Combo Box控件显示“无”,并有另外三项选择 m_ComboBox.AddString(_T("无")); m_ComboBox.AddString(_T("家人")); m_ComboBox.AddString(_T("朋友")); m_ComboBox.AddString(_T("同学")); m_ComboBox.SetCurSel(0); return TRUE; } 单击添加联系人子对话框的保存按钮的响应函数 void ContactAdding::OnBnClickedOk() { //将控件的值赋给成员变量 UpdateData(TRUE); //判断电话号码是否为11位,若不为11位,报错 if (m_Phone2.GetLength() != 11) { MessageBox("请输入11位的电话号码"); } //若电话号码为11位 else{ //check函数判断是否存在重复电话号码,可以重复联系人姓名 if (check() == 1) { m_Name2.TrimLeft(); m_Name2.TrimRight(); //名字不能为空 if (m_Name2.IsEmpty()) { MessageBox("添加联系人信息不能为空"); } //将群组ComboBox索引赋给该类的变量,将在关闭子对话框后使用 else { Group_Index = m_ComboBox.GetCurSel(); CDialog::OnOK(); } } //check函数判断有重复电话号码 else { MessageBox("请不要添加重复的联系人信息"); } } } check函数判断是否存在重复联系人信息 在ContactAdding.h中声明check函数。联系人电话不可以重复,可以一人多号。 ContactAdding.h int check(); ------------------------------------------------------------------------------------------ ContactAdding.cpp int ContactAdding::check() { char Phone[13]; //类型转换 for (int i = 0; i < m_Phone2.GetLength(); i++) { Phone[i] = m_Phone2[i]; } Phone[m_Phone2.GetLength()] = '\0'; //字符通过循环判断是否相同,不能用==判断 for (int i = 0; i < N; i++) { for (int j = 0; j < 11; j++) { //存在数字不相等即电话号码不相等,跳出该电话的循环 if (Phone[j] != new_people[i].Phone[j]) break; //若循环进行到第十一数字,第十一个数字也相等,即该存在相同号码 if (j == 10 && Phone[j] == new_people[i].Phone[j]) //打断循环并返回函数值 return 0; } } //若循环进行完全,即不存在相同号码 return 1; } 5. 单击“删除联系人”按钮的响应函数 删除联系人后相应会更新全局变量 void CMailListtDlg::OnBnClickedButton2() { //当在报表框中选择了一项 while (m_ListCtrl.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED) != -1) { //获得选中项的索引 int nItem; nItem = m_ListCtrl.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED); //删除报表框中的选择的一行 m_ListCtrl.DeleteItem(nItem); //更新全局变量信息 for (int i = nItem; i < N; i++) { strcpy_s(new_people[i].Name, 11,new_people[i + 1].Name); strcpy_s(new_people[i].Phone, 12, new_people[i + 1].Phone); strcpy_s(new_people[i].Group, 9, new_people[i + 1].Group); strcpy_s(new_people[i].Remark, 102, new_people[i + 1].Remark); new_people[i].Group_Index = new_people[i + 1].Group_Index; } //联系人人数减一 N--; //删除、修改联系人按钮灰显 GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE); } //清空备注框(因为选中报表框一项时备注框中会显示该联系人的相应备注) m_Variable.ResetContent(); } 6、单击“报表视图”中一项的响应函数 备注框会显示选中联系人的备注信息。选中联系人后,修改联系人和删除联系人按钮可以使用。 void CMailListtDlg::OnClickList4(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); DWORD dwPos = GetMessagePos(); CPoint point(LOWORD(dwPos), HIWORD(dwPos)); //查看点击位置 m_ListCtrl.ScreenToClient(&point); LVHITTESTINFO lvinfo; lvinfo.pt = point; lvinfo.flags = LVHT_ABOVE; int nItem = m_ListCtrl.SubItemHitTest(&lvinfo); //如果选中了联系人 if (nItem != LB_ERR) { //先清空备注框 m_Variable.ResetContent(); //删除,修改按钮可按 GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE); GetDlgItem(IDC_BUTTON3)->EnableWindow(TRUE); //备注框中显示相应联系人的备注 m_Variable.AddString(new_people[lvinfo.iItem].Remark); } //点中了报表框中的空白处 else { //备注框清空 m_Variable.ResetContent(); //删除,修改联系人按钮灰显 GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE); } *pResult = 0; } 9、单击“修改联系人”按钮的响应函数 在ContactModifying.h中声明两个int类型的变量,使修改联系人子对话框初始化时群组框能显示选中联系人的群组。 ContactModifying.h int RecordList; int RecordGroup_Index ------------------------------------------------------------------------------------------ MailListtDlg.cpp void CMailListtDlg::OnBnClickedButton3() { ContactModifying dlg; //获得列表框选择的位置 int nlist = m_ListCtrl.GetNextItem(-1, LVNI_SELECTED); dlg.RecordList = nlist; dlg.RecordGroup_Index = new_people[nlist].Group_Index; //类型转换 dlg.m_Name3.Format("%s", new_people[nlist].Name); dlg.m_Phone3.Format("%s", new_people[nlist].Phone); dlg.m_Group3.Format("%s", new_people[nlist].Group); dlg.m_Group_Index3 = new_people[nlist].Group_Index; dlg.m_Variable3.Format("%s", new_people[nlist].Remark); //弹出添加联系人子对话框,当子对话框通过保存键关闭时,进行if内的操作 int nIdex = dlg.DoModal(); if (nIdex == IDOK) { m_Variable.ResetContent(); m_ListCtrl.DeleteItem(nlist); //全局变量信息更新+报表视图更新 CString str; int i; //姓名 str = dlg.m_Name3; str.TrimLeft(); str.TrimRight(); for (i = 0; i < str.GetLength(); i++) { new_people[nlist].Name[i] = str[i]; } new_people[nlist].Name[str.GetLength()] = '\0'; //更新报表视图 m_ListCtrl.InsertItem(nlist, str); // 电话 str = dlg.m_Phone3; str.TrimLeft(); str.TrimRight(); for (i = 0; i < str.GetLength(); i++) { new_people[nlist].Phone[i] = str[i]; } new_people[nlist].Phone[str.GetLength()] = '\0'; //更新报表视图 m_ListCtrl.SetItemText(nlist, 1, str); // 备注 str = dlg.m_Variable3; str.TrimLeft(); str.TrimRight(); for (i = 0; i < str.GetLength(); i++) { new_people[nlist].Remark[i] = str[i]; } new_people[nlist].Remark[str.GetLength()] = '\0'; // 群组 new_people[nlist].Group_Index = dlg.m_Group_Index3; if (dlg.m_Group_Index3 == 0) str = "无"; else if (dlg.m_Group_Index3 == 1) str = "家人"; else if (dlg.m_Group_Index3 == 2) str = "朋友"; else if (dlg.m_Group_Index3 == 3) str = "同学"; for (i = 0; i < str.GetLength(); i++) { new_people[nlist].Group[i] = str[i]; } new_people[nlist].Group[str.GetLength()] = '\0'; //更新报表视图 m_ListCtrl.SetItemText(nlist, 2, str); //删除、修改联系人按钮灰显 GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE); } } 进入修改联系人子对话框的初始化函数 群组框显示选中联系人的群组 BOOL ContactModifying::OnInitDialog() { CDialogEx::OnInitDialog(); m_ComboBox3.AddString(_T("无")); m_ComboBox3.AddString(_T("家人")); m_ComboBox3.AddString(_T("朋友")); m_ComboBox3.AddString(_T("同学")); m_ComboBox3.SetCurSel(RecordGroup_Index); return TRUE; } 单击添加联系人子对话框的保存按钮的响应函数 void ContactModifying::OnBnClickedOk() { //将控件的值赋给成员变量 UpdateData(TRUE); //判断电话号码是否为11位 if (m_Phone3.GetLength() != 11) { MessageBox("请输入11位的电话号码"); } //若电话号码为11位 else { //check函数判断重复信息(和添加联系人的check函数不一样) if (check() == 1) { m_Name3.TrimLeft(); m_Name3.TrimRight(); //名字不能为空 if (m_Name3.IsEmpty()) { MessageBox("添加联系人信息不能为空"); } //将群组ComboBox索引赋给该类的变量,将在关闭子对话框后使用 else { m_Group_Index3 = m_ComboBox3.GetCurSel(); CDialog::OnOK(); } } //check函数判断有重复电话号码 else { MessageBox("请不要添加重复的联系人信息"); } } } check函数判断是否存在重复联系人信息(注意和添加联系人的check函数的不同) 在ContactModifying.h中声明check函数。在修改联系人的过程中,存在只修改备注,不修改其他信息的情况,若使用添加联系人的check函数,会出现错误的报错。 ContactModifying.h int check(); ------------------------------------------------------------------------------------------ ContactModifying.cpp int ContactModifying::check() { //类型转换 //姓名 char Name[12]; for (int i = 0; i < m_Name3.GetLength(); i++) { Name[i] = m_Name3[i]; } Name[m_Name3.GetLength()] = '\0'; //电话 char Phone[13]; for (int i = 0; i < m_Phone3.GetLength(); i++) { Phone[i] = m_Phone3[i]; } Phone[m_Phone3.GetLength()] = '\0'; //当m=0时,即修改的电话和选中联系人的电话相同;当m=1时,则不相同 int m = 0; for (int i = 0; i < 11; i++) { if (Phone[i] != new_people[RecordList].Phone[i]) { m = 1; } } for (int i = 0; i < N; i++) { for (int j = 0; j < 11; j++) { //一个数字不相等即电话号码不相等,跳出该电话的循环 if (Phone[j] != new_people[i].Phone[j]) break; //若循环进行到第十一数字,第十一个数字也相等,即该存在相同号码 //m==1即相同号码不为选中联系人电话,判断为真实存在重复电话 if (j == 10 && Phone[j] == new_people[i].Phone[j] && m == 1) return 0; } } //若循环进行完全,即不存在相同号码 return 1; } 8、双击“报表视图”中一项的响应函数 和单击“修改联系人”按钮的响应函数相同。 9、单击“查找”按钮的响应函数 实现根据关键字进行查找联系人的功能。(即输入名字或电话的一部分或者仅选择群组都可以查找到匹配联系人) 存在匹配联系人时报表视图只显示匹配联系人的信息。 void CMailListtDlg::OnClickedButton5() { //将控件值传给成员变量 UpdateData(TRUE); //声明定义一个MyClass对象存储信息 MyClass Find; CString str; //类型转换 //姓名 str = m_Name1; str.TrimLeft(); str.TrimRight(); for (int i = 0; i < str.GetLength(); i++) Find.Name[i] = str[i]; Find.Name[str.GetLength()] = '\0'; //电话 str = m_Phone1; str.TrimLeft(); str.TrimRight(); for (int i = 0; i < str.GetLength(); i++) Find.Phone[i] = str[i]; Find.Phone[str.GetLength()] = '\0'; //索引 //主对话框中的Combo Box索引数比其他子对话框的索引数多一个,因为主对话框中的ComboBox默认不显示,所以要-1 Find.Group_Index = m_zhuGroup.GetCurSel() - 1; CString s1, s2; CString check; int Record[100]; int record = 0; int que[100]; for (int i = 0; i < 100; i++) { que[i] = i; } for (int i = 0; i < N; i++) { //类型转换 s1.Format("%s", Find.Name); s2.Format("%s", Find.Phone); //如果输入查找的群组和当前循环的群组不一样,则进行下一次循环 //自己也没想懂逻辑 if ((new_people[i].Group_Index == -1) || (Find.Group_Index != -1 && Find.Group_Index != new_people[i].Group_Index) || (Find.Group_Index == -1 && new_people[i].Group_Index != -1 && s1.IsEmpty() && s2.IsEmpty())) continue; //如果当前循环的姓名不存在输入查找的姓名或姓名的一部分,则进行下一次循环 s1.Format("%s", Find.Name); s2.Format("%s", new_people[i].Name); if (!s1.IsEmpty() && s2.Find(s1) == -1) continue; //如果当前循环的电话不存在输入查找的电话或电话的一部分,则进行下一次循环 s1.Format("%s", Find.Phone); s2.Format("%s", new_people[i].Phone); if (!s1.IsEmpty() && s2.Find(s1) == -1) continue; Record[que[record]] = i; record ++; } //弹窗显示查找到多少名联系人 check.Format("共查到%d条联系人", record); MessageBox(check); //如果找到匹配联系人,清空报表视图,只显示匹配联系人信息 if (record > 0) { m_ListCtrl.DeleteAllItems(); for (int i = 0; i < record; i++) { m_ListCtrl.InsertItem(i, new_people[Record[que[i]]].Name); m_ListCtrl.SetItemText(i, 1, new_people[Record[que[i]]].Phone); m_ListCtrl.SetItemText(i, 2, new_people[Record[que[i]]].Group); } } } 10、单击“显示全部”按钮的响应函数 void CMailListtDlg::OnClickedButton6() { //清空报表视图,因为查找后只显示匹配联系人信息 m_ListCtrl.DeleteAllItems(); //清空查找框中输入的信息 m_Name11.SetWindowTextA(""); m_Phone11.SetWindowTextA(""); m_zhuGroup.SetCurSel(0); //报表视图显示所有联系人信息,提取全局变量 for (int i = 0; i < N; i++) { m_ListCtrl.InsertItem(i, new_people[i].Name); m_ListCtrl.SetItemText(i, 1, new_people[i].Phone); m_ListCtrl.SetItemText(i, 2, new_people[i].Group); } } 11、单击“保存”按钮的响应函数 将全局变量中的联系人信息写出文件保存,并用于下次读入。 void CMailListtDlg::OnBnClickedButton7() { CStdioFile file; file.Open("test.txt", CFile::modeCreate | CFile::modeWrite); CString str; if (new_people[0].Group_Index != -1) { for (int i = 0; i < N; i++) { //姓名 str.Format("%s\n", new_people[i].Name); file.WriteString(str); //电话 str.Format("%s\n", new_people[i].Phone); file.WriteString(str); //群组 str.Format("%s\n", new_people[i].Group); file.WriteString(str); //群组索引 str.Format("%d\n", new_people[i].Group_Index); file.WriteString(str); //备注 str.Format("%s\n", new_people[i].Remark); file.WriteString(str); } } MessageBox("保存成功"); CDialogEx::OnCancel(); }
MFC是Microsoft Foundation Class的缩写,是一个用于Windows操作系统的C++类库,可以方便地开发GUI应用程序。下面是一些基本思路来设计一个通讯录系统:
- 界面设计:使用MFC框架创建一个对话框窗口,包含添加联系人、编辑联系人、删除联系人、搜索联系人和显示所有联系人等功能按钮。
- 数据存储:使用SQLite等关系型数据库,设计合适的表结构来存储联系人信息,如姓名、电话号码、邮箱、地址等。
- 添加联系人:当用户点击添加联系人按钮时,弹出一个新的对话框窗口,用户可以输入联系人的详细信息,然后将其存储到数据库中。
- 编辑联系人:当用户选择一个已经存在的联系人并点击编辑按钮时,弹出一个新的对话框窗口,在该窗口中显示选定联系人的详细信息,用户可以修改任何字段,保存修改后的信息到数据库中。
- 删除联系人:当用户选择一个已经存在的联系人并点击删除按钮时,弹出一个确认对话框窗口,以免误删,然后从数据库中删除该联系人。
- 搜索联系人:当用户在搜索文本框中输入关键字并点击搜索按钮时,根据输入的关键字查询数据库,并在一个列表视图控件中显示符合条件的联系人。
- 显示所有联系人:当用户点击显示所有联系人按钮时,从数据库中获取所有联系人信息,并在一个列表视图控件中显示。
- 数据校验:在添加或编辑联系人时,需要对输入的数据进行合法性校验,例如电话号码必须为数字、邮箱地址必须符合格式等。
- 错误处理:在程序运行过程中,可能会出现一些错误,如数据库连接失败、文件读写异常等,需要对这些错误进行捕获和处理,以便及时通知用户并解决问题。
- 界面美化:最后可以对界面进行美化,包括使用合适的字体、颜色和布局来提高用户体验。
在 MFC 应用程序中添加窗口控件的步骤如下:
- 打开资源视图,双击应用程序的 .rc 文件,打开资源编辑器。
- 在资源编辑器中选择一个对话框或者新建一个对话框。
- 在工具箱中选择想要添加的控件,比如按钮、编辑框、列表框等。
- 在对话框上使用鼠标拖动绘制出控件的大小和位置。
- 右键单击控件,选择属性,可以设置控件的属性,比如字体、颜色、默认文本等。
- 在代码中使用成员变量或者 GetDlgItem 函数获取控件的句柄,可以对控件进行操作,比如设置文本、字符格式、位置等。
- 如果需要响应控件的事件,比如按钮点击事件,可以通过添加响应函数的方式来实现。在类的消息映射表中添加 ON_CONTROL_RANGE 或者 ON_MESSAGE 宏,然后在类中实现响应函数即可。
以上是在 MFC 应用程序中添加窗口控件的基本步骤,需要根据实际情况进行具体实现。