在学习MFC总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
07-MFC_20day
一、项目配置
1、创建项目
2、预处理 C4996 :_CRT_SECURE_NO_WARNINGS
3、窗口进行简单处理
(1)修改窗口图标,setClassLong(窗口句柄,修改图标,具体图标加载)
(2)标题 setTitle 分左右侧:左侧:CSaleSystemDoc-OnNewDocument;右侧:CMainFrame-OnCreate中修改
(3)设置窗口大小:MoveWindow
(4)居中CenterWindow
CMainFrame-OnCreate中:
1 //设置图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数 2 SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN)); 3 4 //修改标题 右侧标题 5 SetTitle(TEXT("2020/06/26")); 6 7 //修改窗口大小 8 MoveWindow(0, 0, 800, 500); 9 10 //居中显示 11 CenterWindow();
CSaleSystemDoc-OnNewDocument中:
1 //左侧标题设置 2 SetTitle(TEXT("销售管理系统"));
二、CInfoFile引入
1、文件内容及格式 添加资源
在项目文件夹下添加login.ini,中:
1 斧头帮帮主 2 123456
在项目文件夹下添加stock.txt,中:
1 商品ID|商品名称|商品价格|库存 2 1|商品1|123|440 3 2|商品2|1123|555 4 3|商品3|1333|541 5 4|商品4|144423|547 6 5|商品5|14423|555 7 6|商品6|1123|554 8 7|商品7|1223|544 9 8|商品8|1233|555 10 9|商品9|1234|554 11 10|商品10|1523|555 12 11|商品11|5123|555 13 12|商品12|133|333 14 13|商品13|444|444 15 14|商品14|1111|111 16 15|测试|10|8
2、将CInfoFile类导入到项目中
(1)添加CInfoFile类
(2)头文件(InfoFile.h)的设计
定义两个配置文件路径宏:
1 #define _F_LOGIN "./login.ini" 2 #define _F_STOCK "./stock.txt"
添加文件信息结构体,具体如下:
1 struct msg 2 { 3 int id; //商品id 4 string name; //商品名,别忘包含相应头文件 5 int price; //商品价格 6 int num; //商品个数 7 };
商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量:
1 list<msg> ls; //存储商品容器,别忘包含相应头文件 2 int num; //用来记录商品个数
项目中需要读写的文件有两种,用户信息配置文件和商品信息文件。具体 API 接口如下:
1 //读取登陆信息 2 void ReadLogin(CString &name, CString &pwd); 3 4 //修改密码 5 void WritePwd(char* name, char* pwd); 6 7 // 读取商品数据 8 void ReadDocline(); 9 10 //商品写入文件 11 void WirteDocline(); 12 13 //添加新商品 14 void Addline(CString name, int num, int price);
InfoFile.h全部代码如下:
1 #pragma once 2 3 #include <list> 4 #include <fstream> 5 #include <iostream> 6 #include <string> 7 8 #define _F_LOGIN "./login.ini" 9 #define _F_STOCK "./stock.txt" 10 11 using namespace std; 12 13 struct msg 14 { 15 int id; //商品id 16 string name; //商品名 17 int price; //商品价格 18 int num; //商品个数 19 }; 20 21 class CInfoFile 22 { 23 public: 24 CInfoFile(); 25 ~CInfoFile(); 26 27 //读取登陆信息 28 void ReadLogin(CString &name, CString &pwd); 29 30 //修改密码 31 void WritePwd(char* name, char* pwd); 32 33 // 读取商品数据 34 void ReadDocline(); 35 36 //商品写入文件 37 void WirteDocline(); 38 39 //添加新商品 40 void Addline(CString name, int num, int price); 41 42 list<msg> ls; //存储商品容器 43 int num; //用来记录商品个数 44 };
InfoFile.cpp全部代码如下:
1 #include "stdafx.h" 2 #include "InfoFile.h" 3 4 5 CInfoFile::CInfoFile() 6 { 7 } 8 9 10 CInfoFile::~CInfoFile() 11 { 12 } 13 14 //读取登录信息 15 void CInfoFile::ReadLogin(CString &name, CString &pwd) 16 { 17 ifstream ifs; //创建文件输入对象 18 ifs.open(_F_LOGIN); //打开文件 19 20 char buf[1024] = { 0 }; 21 22 ifs.getline(buf, sizeof(buf)); //读取一行内容 23 name = CString(buf); //char *转换为CString 24 25 ifs.getline(buf, sizeof(buf)); 26 pwd = CString(buf); 27 28 ifs.close(); //关闭文件 29 } 30 31 //修改密码 32 void CInfoFile::WritePwd(char* name, char* pwd) 33 { 34 ofstream ofs; //创建文件输出对象 35 ofs.open(_F_LOGIN); //打开文件 36 37 ofs << name << endl; //name写入文件 38 ofs << pwd << endl; //pwd写入文件 39 40 ofs.close(); //关闭文件 41 } 42 43 //读取商品信息 44 void CInfoFile::ReadDocline() 45 { 46 ifstream ifs(_F_STOCK); //输入方式打开文件 47 48 char buf[1024] = { 0 }; 49 num = 0; //初始化商品数目为0 50 ls.clear(); 51 //取出表头 52 ifs.getline(buf, sizeof(buf)); 53 54 while (!ifs.eof()) //没到文件结尾 55 { 56 msg tmp; 57 58 ifs.getline(buf, sizeof(buf)); //读取一行 59 num++; //商品数目加一 60 61 //AfxMessageBox(CString(buf)); 62 char *sst = strtok(buf, "|"); //以“|”切割 63 if (sst != NULL) 64 { 65 tmp.id = atoi(sst); //商品id 66 } 67 else 68 { 69 break; 70 } 71 72 sst = strtok(NULL, "|"); 73 tmp.name = sst; //商品名称 74 75 sst = strtok(NULL, "|"); 76 tmp.price = atoi(sst); //商品价格 77 78 sst = strtok(NULL, "|"); 79 tmp.num = atoi(sst); //商品数目 80 81 ls.push_back(tmp); //放在链表的后面 82 } 83 84 ifs.close(); //关闭文件 85 } 86 87 //商品写入文件 88 void CInfoFile::WirteDocline() 89 { 90 ofstream ofs(_F_STOCK);//输出方式打开文件 91 92 if (ls.size() > 0) //商品链表有内容才执行 93 { 94 ofs << "商品ID|商品名称|商品价格|库存" << endl; //写入表头 95 96 //通过迭代器取出链表内容,写入文件,以“|”分隔,结尾加换行 97 for (list<msg>::iterator it = ls.begin(); it != ls.end(); it++) 98 { 99 ofs << it->id << "|"; 100 ofs << it->name << "|"; 101 ofs << it->price << "|"; 102 ofs << it->num << endl; 103 } 104 } 105 106 ofs.close();//关闭文件 107 } 108 109 //添加新商品 110 //name:商品名称,num:库存,price:价格 111 void CInfoFile::Addline(CString name, int num, int price) 112 { 113 msg tmp; 114 115 if (ls.size() > 0) 116 { 117 //商品名称,库存,价格有效 118 if (!name.IsEmpty() && num > 0 && price > 0) 119 { 120 tmp.id = ls.size() + 1; //id自动加1 121 CStringA str; 122 str = name; //CString转CStirngA 123 tmp.name = str.GetBuffer(); //CStirngA转char *,商品名称 124 tmp.num = num; //库存 125 tmp.price = price; //价格 126 127 ls.push_back(tmp); //放在链表的后面 128 } 129 } 130 }
3、进行简单测试,读取用户名、密码、修改密码
三、登录窗口实现
1、插入对话框
1)添加对话框资源(ID修改为DIALOG_LOGIN),添加所需控件
2、对界面进行布局
3、添加类:
2)选中对话框 -> 右击 -> 添加类 -> 类名:CLoginDlg
4、添加变量 m_user、m_pwd;根据需求,控件关联所需变量;用户名编辑区关联CString m_user,密码登陆框关联CString m_pwd。
5、初始化:用户名、密码
(1)在对话框类中,重写 OnInitDialog 函数,进行初始化,设置一些默认登录信息
(2)登陆窗口的创建
在应用程序类CSaleSystemApp的InitInstance() 里面的APP 创建之前创建登陆对话框:
6、功能实现
(1)登录按钮
1 //登陆按钮处理函数 2 void CLoginDlg::OnBnClickedButton1() 3 { 4 // TODO: 在此添加控件通知处理程序代码 5 6 UpdateData(TRUE); //更新控件的数据到对应的变量 7 8 CInfoFile file; //创建操作文件类对象,需要头文件#include "InfoFile.h" 9 CString user, pwd; 10 11 //读取配置文件,获取用户名密码,参数为引用传递 12 file.ReadLogin(user, pwd); 13 14 if (m_user == user)//用户名相等 15 { 16 if (m_pwd != pwd) 17 { 18 MessageBox(_T("密码错误")); 19 m_user.Empty(); //清空 20 m_pwd.Empty(); 21 } 22 else 23 { 24 CDialogEx::OnOK(); 25 } 26 } 27 else 28 { 29 MessageBox(_T("用户名不存在")); 30 m_user.Empty(); 31 m_pwd.Empty(); 32 } 33 }
(2)取消按钮
1 //取消按钮功能实现 2 void CLoginDlg::OnBnClickedButton2() 3 { 4 // TODO: 在此添加控件通知处理程序代码 5 exit(0); //结束整个程序 6 }
(3)右上角关闭按钮功能实现
选中对话框模板 -> 右击 -> 属性 -> 消息 -> WM_CLOSE
1 //关闭按钮 2 void CLoginDlg::OnClose() 3 { 4 // TODO: 在此添加消息处理程序代码和/或调用默认值 5 exit(0); //结束整个程序 6 7 CDialogEx::OnClose(); 8 }
(4)编辑区回车键关闭对话框问题解决——重写OnOk
四、静态拆分窗口
1、拆分窗口对象
自定义MFC视图类
》自定义两个类:CSelectView和CDispalyView(它的基类必须是视图类)。
》CSelectView继承于CTreeView,CDispalyView继承于CFormView。
2、创建静态拆分
通过CSplitterWnd类拆分窗口
CMainFrame类中,声明CSplitterWnd类型的对象:
3、具体拆分窗口
重写框架类CMainFrame的OnCreateClient函数
把OnCreateClient()函数的返回值改为Return TRUE:
静态拆分实现代码如下:
1 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 2 { 3 // TODO: 在此添加专用代码和/或调用基类 4 5 // 静态拆分窗口,1行2列,CSplitterWnd::CreateStatic 6 m_spliter.CreateStatic(this, 1, 2); 7 8 // 创建视图:CSplitterWnd::CreateView 9 //0, 0 : 放在第0行第0列的位置 10 //RUNTIME_CLASS(CSelectView) :需要头文件#include "SelectView.h", CSelectView在SelectView.h中声明 11 // CSize(250, 500):指定视图宽度和高度 12 //pContext : 为OnCreateClient()最后一个形参 13 m_spliter.CreateView(0, 0, RUNTIME_CLASS(CSelectView), CSize(200, 500), pContext); 14 15 //0, 1: 放在第0行第1列的位置 16 //CDispalyView,需要头文件#include "DispalyView.h" 17 m_spliter.CreateView(0, 1, RUNTIME_CLASS(CDispalyView), CSize(600, 500), pContext); 18 19 //return CFrameWnd::OnCreateClient(lpcs, pContext); 20 return TRUE; 21 }
五、树视图功能实现
1、数据准备
(1)加载图标资源
(2)图标资源ID改为:IDI_ICON_RE
2、获取到树控件 GetTreeCtrl()
CSelectView类中声明相应变量:
3、设置图片集合 、设置节点
重写CSelectView的OnInitUpdate函数,在CSelectView的OnInitUpdate函数中,完成初始化功能
1 void CSelectView::OnInitialUpdate() 2 { 3 CTreeView::OnInitialUpdate(); 4 5 // TODO: 在此添加专用代码和/或调用基类 6 7 //图标资源的加载 CWinApp::LoadIcon 8 //IDI_ICON_RE为图标资源ID 9 HICON icon = AfxGetApp()->LoadIconW(IDI_ICON_RE); 10 11 //图片列表的创建 CImageList::Create 12 //30, 30:指定图标的宽度和高度 13 //ILC_COLOR32:图标格式 14 //1, 1:有多少图标就写多少 15 m_imageList.Create(30, 30, ILC_COLOR32, 1, 1); 16 17 //图片列表追加图标 CImageList::Add 18 m_imageList.Add(icon); 19 20 //获取数视图中的树控件 CTreeView::GetTreeCtrl 21 m_treeCtrl = &GetTreeCtrl(); 22 23 //数控件设置图片列表 CTreeCtrl::SetImageList 24 m_treeCtrl->SetImageList(&m_imageList, TVSIL_NORMAL); 25 26 //树控件设置节点 CTreeCtrl::InsertItem 27 m_treeCtrl->InsertItem(TEXT("个人信息"), 0, 0, NULL); 28 m_treeCtrl->InsertItem(TEXT("销售管理"), 0, 0, NULL); 29 m_treeCtrl->InsertItem(TEXT("库存信息"), 0, 0, NULL); 30 m_treeCtrl->InsertItem(TEXT("库存添加"), 0, 0, NULL); 31 m_treeCtrl->InsertItem(TEXT("库存删除"), 0, 0, NULL); 32 }
4、捕获事件(选项修改事件)
1 void CSelectView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) 2 { 3 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); 4 // TODO: 在此添加控件通知处理程序代码 5 *pResult = 0; 6 7 //获取当前节点选中项目 CTreeCtrl::GetSelectedItem 8 HTREEITEM item = m_treeCtrl->GetSelectedItem(); 9 10 //获取选中项的文本内容 CTreeCtrl::GetItemText 11 CString str = m_treeCtrl->GetItemText(item); 12 //MessageBox(str); 13 14 if (str == TEXT("个人信息")) 15 { 16 } 17 else if (str == TEXT("销售管理")) 18 { 19 } 20 else if (str == TEXT("库存信息")) 21 { 22 } 23 else if (str == TEXT("库存增加")) 24 { 25 } 26 else if (str == TEXT("库存删除")) 27 { 28 } 29 }
六、个人信息界面布局
七、个人信息的界面挂载
1、自定义消息 define 宏 NM_A~E
2、在分界宏声明自定义消息 :ON_MESSAGE(NM_A, OnMyChange)
3、实现OnMyChange函数:
afx_msg LRESULT OnMyChange(WPARAM wParam, LPARAM lParam);
4、在SelectView发送自定义消息
1 LRESULT CMainFrame::OnMyChange(WPARAM wParam, LPARAM lParam) 2 3 { 4 5 6 7 }
5、捕获消息,进行界面挂载
八、个人信息功能实现
1、搭建界面
2、功能实现
3、初始化界面:身份、用户名
4、修改密码功能
(1)有效性验证:内容不能为空,密码两次输入要一致,与原密码不一样
(2)取消:清空内容
九、销售管理界面
十、添加商品
十一、添加新商品
十二、菜单栏添加
在学习MFC总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量: